Название: Модель данных для многопоточного использования Отправлено: ammaximus от Декабрь 22, 2011, 15:12 Вообщем задача такова - несколько процессов используют модель данных, читают, пишут. Сама модель должна ежесекундно пересчитывать свои поля и удалять устаревшие.
Хотелось бы такую модель данных, которая будет позволять следующее: 1. Доступ к инкапсулированному массиву данных, функции добавления, удаления элементов, обращения к конкретному элементу, а также возможность делать циклический обход элементов. Это чтобы люди которые моделью будут пользоваться увствовали себя комфортно. 2. Защищенная модель (мьютекс), дающая право записи только одному процессу в определенное время. 3. Модель, содержащая служебные демоны и дающая им полный и быстрый доступ к своим полям. 4. Также неплохо было бы давать возможность демонам выполнятся во время, свободное от обращения других потоков, ну и тем более самих себя (синхронизация демонов). Сначала я пытался унаследовать этот класс от QThread и обойтись без демонов, но потом дошло, что другие процессы не смогут пользоваться ссылками на объекты этого класса и вообще модель теряет смысл. Потом я написал небольшой демон и включил его в объект этой модели, но все начало летать, видимо так нельзя. Еще сделанная мною концепция предоставления итератора наружу во 1 будет вылетать при обращении более 1 потока, а во 2 даже если защитить его мьютексом не будет давать возможность потокам использовать его только для чтения(( Вообще я создаю свою первую многопоточную систему и буду рад любым советам) Код: #ifndef ABSTRACTMASSIV_H Название: Re: Модель данных для многопоточного использования Отправлено: Igors от Декабрь 22, 2011, 18:24 Интересно, хотя кто такие демоны? :) Принципиальные недостатки очевидны, Вы сами о них пишете: если один из пользователей взял итератор, то что с валидностью этого итератора? Напрашивается др. подход: сделать "просто модель" и на нее накрутить (Q)ReadWriteLock, т.е. в 1 момент времени любое число читающих но 1 (и только 1) пишущий. Сделать все обращения через переходничок который будет гарантировать захват + метод AcquireWrite (без него не обойтись).
Название: Re: Модель данных для многопоточного использования Отправлено: ammaximus от Декабрь 23, 2011, 12:35 Э.. В данном случае под демонами подразумеваются процессы которые будут ежесекундно экстраполировать данные в массиве и погибать одновременно с ним. У каждого экземпляра такой модели должен быть свой служебный процесс.
Идея: внутри модели делать объекты типа massivUtil : public QThread, которые будут останавливаться в деструкторе модели. Допустимо ли это? Для меня очень важна циклическая обработка извне, желательно чтобы конструкция была попроще, т.к. будет использоваться посторонними. Есть идеи по этому вопросу? Название: Re: Модель данных для многопоточного использования Отправлено: ammaximus от Декабрь 23, 2011, 12:45 :-[
Меня беспокоит, как реализовать обход большого количества элементов не блокируя надолго мутекс, т.к. на каждой отдельной итерации будет критичным лишь один элемент, а мутексирование итератора тормознет систему надолго, а иначе не будет доступен циклический обход Название: Re: Модель данных для многопоточного использования Отправлено: Igors от Декабрь 23, 2011, 13:22 :-[ "Просто мутекс" здесь вообще не годится. Нужно ориентироваться на ReadWriteLock имея ввиду: это название условно, более точная формулировка shared/exclusive (access)Меня беспокоит, как реализовать обход большого количества элементов не блокируя надолго мутекс, т.к. на каждой отдельной итерации будет критичным лишь один элемент, а мутексирование итератора тормознет систему надолго, а иначе не будет доступен циклический обход Э.. В данном случае под демонами подразумеваются процессы которые будут ежесекундно экстраполировать данные в массиве и погибать одновременно с ним. У каждого экземпляра такой модели должен быть свой служебный процесс. Идеи простые: "не выделываться" (скажем так) ни с какими демонами, а сделать это действие explicit (явным). Если модель сама собой занимается, то известно откуда/по каким причинам, оттуда и надо крутить. Простой пример: нет активных пользователей - и вот кто-то щемится по записи/чтению. Вот тут и время "обновиться" а потом уже разрешить доступ.Идея: внутри модели делать объекты типа massivUtil : public QThread, которые будут останавливаться в деструкторе модели. Допустимо ли это? Для меня очень важна циклическая обработка извне, желательно чтобы конструкция была попроще, т.к. будет использоваться посторонними. Есть идеи по этому вопросу? Вообще лучше рассуждать так: если хотя бы 1 из пользователей читает модель - никто не может ее менять, необходимо дождаться конца всех чтений. Это ограничение жестко и неприятно, но его не обойти. Если же речь идет о блокировке индивидуальных элементов (не меняя их числа и порядка) - так можно, но это уже др. песня Название: Re: Модель данных для многопоточного использования Отправлено: ammaximus от Декабрь 23, 2011, 15:05 К сожалению сделать явно не получиться: модель работать будет в реальном времени и за секунду ее прочтут десятки процессов с разным приоритетом - кому то надо чаще кому то нет, так что таким методом мы можем не дойти до обновления. Хотя это наверное напрасно, скорее всего успеет..
Тогда проблема только одна - обновление должно быть привязано ко времени, а не к подключенным элементам. Можно конечно время засекать и сразу на много экстраполировать, но я хочу чтобы подключенный процесс выполнился как можно быстрее, а не ждал выполнения каких то там служебных задач. К тому же мне не нужна такая точность, чтобы перед каждым запуском была экстраполяция, мне важнее скорость работы основных процессов. Название: Re: Модель данных для многопоточного использования Отправлено: ammaximus от Декабрь 23, 2011, 15:13 Наклепал демона, вот что получилось. В принципе запустил на основной модели - работает и делает все как нужно.
Код: class Massivutil: public QThread{ Попутный вопрос, чтобы тему не создавать, я удаляю что то из вектора erase(iterator). Я зная что erase возвратит указатель на следующий элемент, но что в данный момент стало с самим итератором? В моей функции не возможно получить результат erase, нужно ли переходить к след элементу (итератор++)? У меня в коде и без этого работает (см закомментированный участок) Название: Re: Модель данных для многопоточного использования Отправлено: Igors от Декабрь 23, 2011, 16:15 К сожалению сделать явно не получиться: Может я чего-то не понял, но Вы вообще думаете защищать доступ к данным или как? Вы не можете писать пока кто-то читает, поэтому как раз по таймеру обновление имеет мало шансов прорваться. Нормально накапливать изменения, потом флашить. Попутный вопрос, чтобы тему не создавать, я удаляю что то из вектора erase(iterator). Я зная что erase возвратит указатель на следующий элемент, но что в данный момент стало с самим итератором? Это конкретно для каждого контейнера, оговаривается стандартом. Для std::vector итератор становится НЕ валиден.Наклепал демона, вот что получилось. В принципе запустил на основной модели - работает и делает все как нужно. Ну так и слава богу - жизнь покажет и жизнь научит :)Название: Re: Модель данных для многопоточного использования Отправлено: ammaximus от Декабрь 26, 2011, 08:02 Цитировать Нормально накапливать изменения, потом флашить Я понимаю, что так лучше, но пока реализация обрисовывается мутно. Спасибо, буду экспериментировать :)Название: Re: Модель данных для многопоточного использования Отправлено: ammaximus от Декабрь 26, 2011, 12:19 Цитировать по таймеру обновление имеет мало шансов прорваться Цитировать To ensure that writers aren't blocked forever by readers, readers attempting to obtain a lock will not succeed if there is a blocked writer waiting for access, even if the lock is currently only accessed by other readers. Also, if the lock is accessed by a writer and another writer comes in, that writer will have priority over any readers that might also be waiting. Насколько я понял то, что написано в документации, таймерные пишущие потоки смогут попасть внутрь, т.к. имеют приоритет. Название: Re: Модель данных для многопоточного использования Отправлено: Igors от Декабрь 28, 2011, 15:32 Цитировать To ensure that writers aren't blocked forever by readers, readers attempting to obtain a lock will not succeed if there is a blocked writer waiting for access, even if the lock is currently only accessed by other readers. Also, if the lock is accessed by a writer and another writer comes in, that writer will have priority over any readers that might also be waiting. Насколько я понял то, что написано в документации, таймерные пишущие потоки смогут попасть внутрь, т.к. имеют приоритет. В обновлении данных по таймеру нет ничего плохого, но так или иначе писатель должен знать что и как обновлять. Напр если ничего не изменилось - вероятно и обновлять нечего. Или если данные обновлены но никто из читателей не успел их прочитать - опять впустую. Др. словами просто так лупить по таймеру - неэффективно |