pokk
Помогающий
Offline
|
|
« : 23-03-2017 04:51 » |
|
Есть три модуля, первый принимает данные и складывает в кольцевой буфер, второй и третий модуль достает данные из буфера и один записывает данные в файл,другой выдает их напрямую. Так вот как правильно сделать синхронизацию второго и третьего модуля ? Что бы они дожидались друг друга.
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #1 : 23-03-2017 05:02 » |
|
pokk, пусть буфер содержит элементы типа T. Добавь в T два флага - "записан в файл" , "передан напрямую". Любой из двух читающих модулей обрабатывает элемент и выставляет свой флаг (если флаг уже был выставлен, то обработка уже не требуется). Любой модуль, увидевший, что у элемента все флаги выставлены, удаляет элемент из буфера
|
|
|
Записан
|
|
|
|
pokk
Помогающий
Offline
|
|
« Ответ #2 : 23-03-2017 06:21 » |
|
Спасибо за ответ, а как примерно будет выглядит код у потребителя на си ? У меня получилось что в одном потребителе это будет так а другом GetFlagFile GetFlagOut местами буду поменяны, правда мне это как раз и не нравится что как-то не едино все получается. if(GetFlagFile()){ //Если стоит флаг обработки "записан в файл" (в GetFlagFile сбросить его) //Записать в файл if(!GetFlagOut()){ //Если нету флага обработки "передан напрямую" Удалить из буфера Достать следуюший элементы (и установить флаги на обработку) } }
|
|
|
Записан
|
|
|
|
Ochkarik
|
|
« Ответ #3 : 23-03-2017 07:34 » |
|
а зачем нужна синхронизация второго с третьим модулем? или наоборот? они ж наверное для того и сделаны чтоб разделить ...
|
|
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
pokk
Помогающий
Offline
|
|
« Ответ #4 : 23-03-2017 08:33 » |
|
Что бы данные доставались из кольцевого буфера одни, как для второго модуля так и для третьего. И в случае если в кольцевом буфере находится больше одной порции данных, не получилась так что, второй модуль обе порции записал, когда третий модуль только одну порцию выдал.
PS: А задача простая надо просто принять и записать некий сигнал , и что бы было видно как он записывается, делаю одновременный вывод его.
|
|
|
Записан
|
|
|
|
Dale
|
|
« Ответ #5 : 23-03-2017 09:01 » |
|
Потребителям нет никакой необходимости ждать друг друга. Нужен процесс/поток, который читает данные из буфера производителя и помещает их в две очереди - одна для визуального отображения, другая для записи в файл. Тогда изображение не будет дергаться, если запись идет неравномерно. Типовой паттерн проектирования Wire Tap.
|
|
|
Записан
|
Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.
Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard
Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
|
|
|
Ochkarik
|
|
« Ответ #6 : 23-03-2017 09:13 » |
|
pokk, Что бы данные доставались из кольцевого буфера одни, как для второго модуля так и для третьего. И в случае если в кольцевом буфере находится больше одной порции данных, не получилась так что, второй модуль обе порции записал, когда третий модуль только одну порцию выдал.
PS: А задача простая надо просто принять и записать некий сигнал , и что бы было видно как он записывается, делаю одновременный вывод его.
на сигналах я собаку съел) и на таких задачах в частности. данные у вас в любом случае одни и те же будут. других у вас нет. при отсутствии синхронизации между принимающими модулями - просто что то может произойти чуть раньше(запись или отображение) что то чуть позже. но оператор все равно все что пришло - увидит, а модуль записи все равно - все запишет. так что еще раз спрошу - зачем вам синхронизация между этими процессами?)
|
|
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
pokk
Помогающий
Offline
|
|
« Ответ #7 : 23-03-2017 10:11 » |
|
Dale, я так понял что бы сделать вторую очередь придется копировать данные ? Это копирование не когда мне не нравится, видать по этому и парюсь с такими вопросами, пока подумываю настроить прием данных сразу в две очереди. Ochkarik, так вот то что произойдет быстрее, а эта запись она в 20 раз быстрее чем передача сигнала, то в случае если в очереди было несколько пакетов на запись то они спокойно запишутся, и удалятся из очереди пока "Передатчик" отправляет один пакет, и после того как он выдаст его он потеряет несколько пакетов. Да возможно я сделал не совсем правильно кольцевой буфер, но сначала делал с расчетом на одного потребителя, по этому и сделал всего 3 функции: 1) положить в буфер. 2) достать из буфера(и там сразу удаление из очереди происходит). 3) Выдать количество пакетов в очереди. Пытался минимизировать количество функций что бы в основном алгоритме не городить, удаление из очереди и тд, а то потом происходит сильное загромождение его и сложно разбираться. PS: Считываю сигнал по байтно, но потом формирую его в пакеты по 300 байт, и именно их и буферизирую, точнее их адреса.
|
|
|
Записан
|
|
|
|
Dale
|
|
« Ответ #8 : 23-03-2017 11:39 » |
|
что бы сделать вторую очередь придется копировать данные ? Если есть желание копировать - копируйте на здоровье. Если нет - ставьте в очередь указатель на блок данных, ссылку, индекс в пуле буферов - что угодно, что уже используется в системе. С кольцевым буфером тоже можно работать параллельно - один указатель для производителя и два отдельных для каждого потребителя. Пусть каждый потребитель, обработав данные, передвигает свой личный указатель на шаг.
|
|
|
Записан
|
Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.
Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard
Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
|
|
|
Ochkarik
|
|
« Ответ #9 : 23-03-2017 13:40 » |
|
да, два указателя/индекса и все будет хорошо.
PS удобно делать на атомарных инкрементах/декрементах
PPS две переменные - количество необработанного. читать и писать по кольцу хоть побайтно хоть поблочно. при записи инкремент обоих, при чтении декремент. при записи можно тестировать оба на переполнение буфера при чтении читать пока не станет нулевым(данные кончились)
|
|
« Последнее редактирование: 23-03-2017 13:51 от Ochkarik »
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
Михалыч
|
|
« Ответ #10 : 23-03-2017 13:51 » |
|
А мне вот интересно зайти с другой стороны... Запись в файл - зачем? Для того, чтобы потом смотреть-анализировать, видимо. Ну, или на "аварийный" случай. Велика ли важность, насколько синхронно данные будут "писаться" в файл и передаваться? Пусть себе пишутся данные из своей очереди, важно, чтобы они все записались, а что там передалось на отображение (я так понял) - через секунду-две оператор уже может и не вспомнить... А в файле все есть - берите и смотрите... Так что я пока в принципе не вижу такой необходимости чтобы "...не получилась так что, второй модуль обе порции записал, когда третий модуль только одну порцию выдал..." Может я задачу недопонял... Но вариант распихать данные в 2 очереди - на запись и на передачу мне кажется вполне разумным.
|
|
« Последнее редактирование: 23-03-2017 13:56 от Михалыч »
|
Записан
|
Поживем - увидим... Доживем - узнаем... Выживу - учту
|
|
|
Sla
|
|
« Ответ #11 : 23-03-2017 21:18 » |
|
А какой синхронизации идет речь?
Что и как там принимает первый модуль все равно Его задача выставить lock на время записи
Т.е. грубо - реализация транзакций в базах
Если все же есть необходимость в реал тайме - типа, некогда ждать, надо отдать, и забыть
То под каждую транзакцию выделяется буфера, заведомо больший входных данных И первый модуль сам разруливает своим внутренними ресурсами
|
|
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
RXL
|
|
« Ответ #12 : 23-03-2017 21:35 » |
|
Я бы использовал счетчик ссылок на объект. Последний release удаляет объект или как-то иначе утилизирует. Изначально счетчик равен единице. При постановке в очередь (очередь указателей) увеличиваем его на единицу. После постановки уменьшаем на единицу. Каждый потребитель после обработки уменьшает счетчик на единицу. Если, к примеру, какой-то потребитель захочет поставить указатель в очередь другому потребителю, то счетчик не меняем. В этой схеме объект живет ровно пока он нужен. Создавший его производитель может и не знать о его дальнейшей судьбе.
Реализация счетчика через методы (или функции, если это Си). В методах использовать атомарные операции инкремента/декремента. Эти же методы отвечают за утилизацию объекта.
|
|
« Последнее редактирование: 23-03-2017 21:37 от RXL »
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #13 : 24-03-2017 04:39 » |
|
pokk, насколько я понял, у тебя приоритет - это запись в файл. А передачу сигнала для просмотра делай редко, скажем не чаще, чем раз в 200 мс. Для оператора это равносильно регулятору FPS на экране, но зато можно больше ресурсов отдать под сохранение сигнала в файл. И таки да, две очереди лучше
если неразрывность "показа" сигнала необходима, можно накапливать "кадр" и передавать раз в 200 мс пакет
|
|
« Последнее редактирование: 24-03-2017 04:41 от Алексей++ »
|
Записан
|
|
|
|
pokk
Помогающий
Offline
|
|
« Ответ #14 : 24-03-2017 09:40 » |
|
Спасибо всем за советы, пока остановился на том что прием сигнала будет производиться сразу в две очереди.
|
|
|
Записан
|
|
|
|
|