| 
			| 
					
						| 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 »   |  | 
 
 Спасибо всем за советы, пока остановился на том что прием сигнала будет производиться сразу в две очереди.  |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	|  |