|
|
Регистрация Восстановить пароль |
Повторная активизация e-mail |
Регистрация | Задать вопрос |
Заплачу за решение |
Новые сообщения |
Сообщения за день |
Расширенный поиск |
Правила |
Всё прочитано |
|
Опции темы | Поиск в этой теме |
23.12.2011, 13:21 | #1 |
Старожил
Регистрация: 16.12.2011
Сообщений: 2,329
|
Синхронизация потоков
Мне нужна сама идея. Алгоритм.
Вопрос: как заставить Основной поток ждать, пока данные не будут полностью прочитаны на том конце трубы? Есть класс-обертка, предоставляющий удобный интерфейс работы с консолью. Задача: перехват потока вывода stdout, Допустим, есть такой код: Код:
Соответственно, данные от каутов улетают в трубу, где их читает дочерний поток. Проблема в том, что даже при условии отсутствия буфера у самого sdtout, буфер пайпа устанавливает ОС Windows. В итоге, основной поток нефига не ждет, пока данные от каута будут прочитаны, а сразу же приступает к исполнению следующей инструкции: Код:
"tttttttt1234567890". То бишь, данные от каута пока долетели, консоль уже успела выполнить полностью вторую инструкцию. Вопрос: как заставить Основной поток ждать, пока данные не будут полностью прочитаны на том конце трубы? Я перепробовал кучу всяких способов. Использовал сигналы - все бесполезно. Максимум, чего я добился: это что бы работа основного потока приостанавливалась, пока дочерний читает, что бы не получилось так: "1234tttttttt567890". Но вот заставить основной поток ждать, пока все данные от каута не будут прочитаны - не удалось. |
23.12.2011, 13:42 | #2 |
Software Developer
Участник клуба
Регистрация: 01.03.2011
Сообщений: 1,098
|
Как вариант -- ждать подтверждения получения полного пакета с той стороны.
Для этого имеет смысл "обернуть" исходящий текст служебными символами (STX -- в начале и ETX -- в конце) и ждать ответного сообщения (например, ACK) о том, что пакет данных полностью прочитан. По-хорошему, надо еще добавлять вторым байтом длину сообщения, и предпоследним (перед ETX) -- контрольную сумму пакета.
Болтовня ничего не стоит. Покажите мне код. (c) Linus Torvalds
Помог ответ? -- Поставьте отзыв. Выражения особой благодарности в рублевом эквиваленте отправлять сюда --> R269634919062 |
23.12.2011, 14:00 | #3 | |
Старожил
Регистрация: 16.12.2011
Сообщений: 2,329
|
Цитата:
Иначе теряется смысл самого перехвата. С таким же успехом, проще вообще не пользоваться каутом. Мне нужно, что бы данные в каут отправлялись как обычно. При этом, работа основного потока приостанавливалась до тех пор, пока дочерний не сообщит о том, что он получил всю посылку. Главная проблема заключается в том, что начало передачи самих данных контролирует ОС Windows и... Я нигде не смог найти информацию, но создалось впечатление, что: Получатель <---- труба <----буфер_трубы <----Отправитель Данные от отправителя сначала залетают в буффер пайпа. И уже потом, видимо штатными средствами ОС, данные из буфера отправляются в саму трубу. И уже только тогда, получатель читает очередную порцию. Вот когда данные отправителя перетекли в буфер трубы, основной поток уже приступает к следующей инструкции. А вот когда они из буфера трубы перетекут в саму трубу - это большой вопрос. Может вообще получится так, что Отправитель успеет 100 разных инструкций выполнить, прежде чем Получатель прочитает хотя бы самый первый байт посылки... Но это только моё предположение. Как оно на самом деле я не знаю... Я то думал - данные от отправителя сразу в трубу попадут. Что труба - это и есть файл! В который можно писать, и читать. |
|
23.12.2011, 14:53 | #4 | |
Software Developer
Участник клуба
Регистрация: 01.03.2011
Сообщений: 1,098
|
Цитата:
Болтовня ничего не стоит. Покажите мне код. (c) Linus Torvalds
Помог ответ? -- Поставьте отзыв. Выражения особой благодарности в рублевом эквиваленте отправлять сюда --> R269634919062 |
|
23.12.2011, 15:12 | #5 |
Старожил
Регистрация: 16.12.2011
Сообщений: 2,329
|
С этим я разобрался. Дочерний поток сигналит основному, что бы тот приостановился до тех пор, пока дочерний не уладит все свои дела.
После чего, дочерний поток начинает слушать трубу до тех пор, пока в ней не окажется пустота. Это будит означать, что он выкачал из неё все данные: Код:
Код:
Прежде, чем console начнет выполнять свою штатную работу, она производит проверку: Код:
И пока данные не поступили - дочерний поток тоже никак не сможет просигналить основному, что он начал/окончил чтение. А вот когда данные от каутов поступят в трубу? Это большой вопрос... Как определить, что сработал каут, и данные если прямо сейчас уже не поступили в трубу, то с секунды на секунду там появятся? **** Код:
Последний раз редактировалось _Bers; 23.12.2011 в 15:15. |
23.12.2011, 22:57 | #6 |
Старожил
Регистрация: 16.12.2011
Сообщений: 2,329
|
Вот такое решение имеется на данный момент:
//основной поток 1. Метод консоли первым делом скармливает cout особый символ-метку. После чего ожидает сигнал-разрешение на исполнение инструкции. 2. Получив разрешение (а он обязательное его получит. Либо почти сразу, либо чуть погодя), метод благополучно выполняет инструкцию. 3. После чего анлочит консоль. Дальше см пункт 1. //дочерний поток 4. Данные от каута перехватываются Читателем, и направляются опять таки к консоли. 5. Там они поступают в приёмные покои, и ожидают когда консоль освободится. То есть, дочерний поток будит ждать до тех пор, пока консоль не выполнит свою текущую инструкцию. И только потом сможет доставить посылку. 6. После того, как консоль освободилась, двери приёмных покоев раскрываются, и Читатель заходит внутрь... 7. Происходит анализ последнего символа очередной порции данных. 8. Если этот символ равен символу-метки, значит все, что было до этого символа - обычный каут. И данная метка свидетельствует, что "вся посылка получена" 9. В этом случае, консоль тут же лочится. Теперь Читатель уже с новой посылкой опять будит ждать. 10. А текущие данные отправляются на разделочный стол посылок. 11. После того, как посылка оприходована - Загорается фонарик "разрешение исполнить метод". 12. На этом Читатель завершает свой рабочий цикл, и начинает читать новую посылку. //основной поток 13. А управление возвращается к методу, который запустил символ-метку в поток. Он дождался разрешения на исполнение инструкции. Исполняет её, и разлочивает консоль. 14. см пункт 6. //Примечание. 15. Если пользователь не вызывал методы консоли - соответственно никто её и не лочил, соответственно, читатель со своими посылками сможет прибегать когда захочет. Таким образом достигается синхронизация в обработке посылок от читателя, и методов самой консоли. |
Похожие темы | ||||
Тема | Автор | Раздел | Ответов | Последнее сообщение |
Синхронизация потоков | kardinal94 | Общие вопросы Delphi | 5 | 29.11.2010 21:13 |
Синхронизация потоков | alenka_ej | Помощь студентам | 0 | 03.06.2010 22:20 |
Синхронизация потоков в С++ | erazer89 | Помощь студентам | 0 | 27.04.2010 20:14 |
синхронизация потоков | m_kostik | Win Api | 0 | 26.03.2010 23:56 |