Russian Qt Forum

Qt => Общие вопросы => Тема начата: JayFOX от Март 02, 2010, 20:17



Название: QSharedMemory - сигнал на изменение своими руками
Отправлено: JayFOX от Март 02, 2010, 20:17
Здравствуйте, необходимо как-то отловить изменения разделяемой памяти, пока не смог реализовать ничего кроме проверки по таймеру, но это плохо. Как я понял, есть расширенный вариант - QtSharedMemory, но это только за денежки(?).
Так можно ли как-нибудь с помощью QSharedMemory поймать её изменение?
спасибо.


Название: Re: QSharedMemory - сигнал на изменение своими руками
Отправлено: Пантер от Март 02, 2010, 20:29
А если отнаследоваться и добавить такой фукнционал?


Название: Re: QSharedMemory - сигнал на изменение своими руками
Отправлено: JayFOX от Март 02, 2010, 20:46
Вопрос в том - как узнать, была ли изменена память не по timer event, ну или чтобы приложение(процесс), которое изменяет эту память сообщило всем "клиентам" об изменении.


Название: Re: QSharedMemory - сигнал на изменение своими руками
Отправлено: ритт от Март 02, 2010, 21:18
по таймеру. в своё время других вариантов не придумал...


Название: Re: QSharedMemory - сигнал на изменение своими руками
Отправлено: alexman от Март 02, 2010, 21:28
пока не смог реализовать ничего кроме проверки по таймеру, но это плохо.

Почему это по таймеру плохо?


Название: Re: QSharedMemory - сигнал на изменение своими руками
Отправлено: JayFOX от Март 02, 2010, 21:42
При таймфрейме секунда - мы имеем погрешность в секунду)
при минимальном(1 мс) - это грузит процессор, если же нет, то для меня это ситуация эквивалента
Код:
while(something.isSomeFlag())

Конечно, вышесказанное субъективно, но хочется как лучше.
Видать решение будет найдено в win api. Спасибо за советы.


Название: Re: QSharedMemory - сигнал на изменение своими руками
Отправлено: Igors от Март 02, 2010, 23:47
Была такая необходимость, решил через 2 семафора (созданных в 2 процессах)


Название: Re: QSharedMemory - сигнал на изменение своими руками
Отправлено: JayFOX от Март 03, 2010, 00:04
Можно, пожалуйста, подробнее.


Название: Re: QSharedMemory - сигнал на изменение своими руками
Отправлено: SABROG от Март 03, 2010, 00:39
QSharedMemory сама использует семафоры. Я предлагаю такой вариант. Создать небольшой класс типа SharedEvent, где обязательными полями должны быть ID процесса (условно 0 и 1), ID события. Остальная часть памяти под данные. Помещаем эвент типа SharedEvent::Nothing в нашу разделяемую память. Создаем отдельный поток в каждом процессе и в бесконечном цикле вызываем QSharedMemory::lock(). Первый процесс, который захватил память считывает параметры события, проверяет равен ли ID процесса в эвенте его ID. Если равен, то это предыдущее его событие, которое так и не было обработано другим процессом. Отпускаем память и идем на второй заход. Если ID процесса не равно ему, то проверяем тип события, если это SharedEvent::Nothing, то опять отпускаем память и идем на второй круг. Тем временем другой процесс "подвиснет" в методе QSharedMemory::lock() дожидаясь когда ему вернут память. Когда это происходит, то выполняет с эвентом туже самую процедуру. Предположим, что наше событие имеет ID SharedEvent::ReadyRead и при этом ID процесса в этом событии также не равно тому ID, в котором оно проверяется. Тогда мы забираем данные и передаем их в главный поток. После передачи затираем старое событие новым эвентом, например SharedEvent::ReadyCompleted или просто пустым эвентом SharedEvent::Nothing. Но первый хорош тем, что позволяет на базе отчетов наблюдать за статусом передачи, прогрессбар передвинуть например.
Освобождаем память и второй процесс уже обрабатывает наш эвент или просто проверяет его в цикле.

Как ни крути, а это всё тот же polling, возможно придется добавить таймер в поток, так как оба процесса будут постоянно читать расшаренную память и сравнивать события при простое (SharedEvent::Nothing). Хорошо то, что для GUI приложения это прозрачно.


Название: Re: QSharedMemory - сигнал на изменение своими руками
Отправлено: JayFOX от Март 03, 2010, 00:47
Спасибо, идея интересна, но дальше разблокировки gui мы не ушли. Раздумываю над системой семафоров...


Название: Re: QSharedMemory - сигнал на изменение своими руками
Отправлено: Igors от Март 03, 2010, 01:17
Спасибо, идея интересна, но дальше разблокировки gui мы не ушли. Раздумываю над системой семафоров...
Там получается совсем несложно даже без Qt. Семафоры удобно заводятся в разных процессах (как мне надо было) и могут быть общими. Один процесс записал что-то в shared memory и сделал sem_post (открыл семафор), другой стоял на sem_wait, семафор открылся, забрал из shared memory, отсигналил по второму семафору и опять ушел на sem_wait. Для второго процесса - то же самое. Ну правда в posix семафоры срабатывают по сигналам, это надо проверять. На Вындоуз - аналогично, только с мутексами.


Название: Re: QSharedMemory - сигнал на изменение своими руками
Отправлено: SABROG от Март 03, 2010, 01:37
Всё тоже самое, что ты сейчас написал происходит в QSharedMemory::lock(). А lock() у него на базе QSystemSemaphore (interprocess). Но как я понял человек хотел, чтобы event от ОС пришел "типа поменялось". А с семафорами выходит другая незадача. Один висит в lock'e дожидаясь пока ему освободят ресурс и вроде бы всё хорошо, а вот второму этот ресурс может быть нафиг не нужен, так как команды от пользователя не поступило и сидит ждет в каком-нибудь QEvenLoop сигнала из GUI например или из БД. При этом если связь между процессами нужна двухсторонняя, то уже хрен. А из этого вытекает, что клиент и сервер должны быть разными приложениями, вместо того, чтобы сделать их идентичными и полноправными.


Название: Re: QSharedMemory - сигнал на изменение своими руками
Отправлено: Igors от Март 03, 2010, 03:01
Но как я понял человек хотел, чтобы event от ОС пришел "типа поменялось".
Что человек хочет - это его дело. А моя задача была максимально быстрый обмен данными между 2 процессами (32 и 64 бит) - вот и пришлось крутить через shared memory.


Название: Re: QSharedMemory - сигнал на изменение своими руками
Отправлено: JayFOX от Март 04, 2010, 20:48
События изменения памяти можно получить через api, но это в ситуации и создания памяти через api (fileMapping), но QSharedMemory не даст доступ не qt-приложениям. Вопрос - тогда можно-ли сообщить другому процессу что-либо (например то, что мы изменили память), средствами qt?


Название: Re: QSharedMemory - сигнал на изменение своими руками
Отправлено: SABROG от Март 04, 2010, 20:54
QLocalSocket (named pipe), создан как-раз для IPC.


Название: Re: QSharedMemory - сигнал на изменение своими руками
Отправлено: JayFOX от Март 04, 2010, 22:25
Вопрос уже дурной, но: делам QLocalServer, к нему коннект QLocalSocket
Послать сообщение QLocalSocket::write(...)
а поймать как?

P.S.Не нашел в примере чата.


Название: Re: QSharedMemory - сигнал на изменение своими руками
Отправлено: SABROG от Март 04, 2010, 23:19
Как обычно, ловим сигнал: void QIODevice::readyRead ()

То есть сначала сервер принимает соединение: QLocalSocket * QLocalServer::nextPendingConnection ()   [virtual]
а уж QLocalSocket на базе QIODevice.


Название: Re: QSharedMemory - сигнал на изменение своими руками
Отправлено: ритт от Март 06, 2010, 02:09
всё бы замечательно, но вы же не собираетесь использовать QLocalSocket для уведомления другой стороны о том, что блок шаренной памяти изменился, правда ведь? :Р


Название: Re: QSharedMemory - сигнал на изменение своими руками
Отправлено: JayFOX от Март 06, 2010, 10:48
Да вот я тоже уже думаю, что получается прикольно)) интерес как-то стремится к абсурду)) Спасибо всем кто помог. Правильно-ли я понял - средствами QT не получить сигнал об изменении разделяемой памяти, кроме как lock() lock() и ждать unlock() а потом опять lock()?

P.S. Исключая QLocalSocket.


Название: Re: QSharedMemory - сигнал на изменение своими руками
Отправлено: Igors от Март 06, 2010, 13:16
Правильно-ли я понял - средствами QT не получить сигнал об изменении разделяемой памяти, кроме как lock() lock() и ждать unlock() а потом опять lock()?
Я считаю что да, правильно. Вообще, что есть "сигнал об изменении разделяемой памяти"? (который Вы хотите получить). Допустим процесс 1 пишет что-то в shared memory. Вот сейчас 2 байта записаны, но запись-то продолжается. Вам ведь совсем не нужна реакция на каждое изменение shared memory. По любому процесс 1 должен закончить запись и выставить сигнал/флаг "готово" - а это просто семафор(ы). Ну и делайте их - через lock или по-другому, смысл все равно один.


Название: Re: QSharedMemory - сигнал на изменение своими руками
Отправлено: JayFOX от Март 06, 2010, 13:31
Да, все верно, спасибо.


Название: Re: QSharedMemory - сигнал на изменение своими руками
Отправлено: JayFOX от Март 11, 2010, 19:25
Решил ситуацию с помощью winapi - CreateEvent() и WaitForSingleObject().