|
|
  |
WinAPI - Event`ы работают не корректно |
|
|
|
Feb 10 2014, 14:14
|

Профессионал
    
Группа: Свой
Сообщений: 1 080
Регистрация: 16-11-04
Из: СПб
Пользователь №: 1 143

|
нужно организовать алгоритм: три задачи t1a t1b t2 ( в WinApi это Thread но сути не меняет ) нужно чтобы t1a и t1b выполнили некое действие, выставили готовность чтобы уйти в ожидание и дать управление задаче t2, задача t2 выполняет свое действие, приостанавливает свою работу и разрешает работу t1a и t1b и снова по кругу написал следующее (псевдокод): Код HANDLE events_t1_rdy[2] = { 0 }; HANDLE events_t2_rdy = { 0 };
events_t1_rdy[0] = CreateEvent( NULL, FALSE, FALSE, NULL ); // с автосбросом events_t1_rdy[1] = CreateEvent( NULL, FALSE, FALSE, NULL ); // с автосбросом events_t2_rdy = CreateEvent( NULL, TRUE, FALSE, NULL ); // с ручным сбросом
t1a() { t1a_todo(); SetEvent( events_t1_rdy[0] ); DWORD dwEvent = WaitForSingleObject( events_t2_rdy, 5000 ); assert( dwEvent == WAIT_OBJECT_0 ); }
t1b() { t1b_todo(); SetEvent( events_t1_rdy[1] ); DWORD dwEvent = WaitForSingleObject( events_t2_rdy, 5000 ); assert( dwEvent == WAIT_OBJECT_0 ); }
t2() { DWORD dwEvent = WaitForMultipleObjects( 2, events_t1_rdy, TRUE, 5000 ); assert( dwEvent == WAIT_OBJECT_0 ); t2_todo(); PulseEvent( events_t2_rdy ); } дык вот, один раз в 100тысяч - милллион раз, одна задача (t1a или t1b ) не получает что t2 готов и ловлю dwEvent = 258 = 0x102 = TIMEOUT как лечится ?
--------------------
Марс - единственная планета, полностью населенная роботами (около 7 штук).
|
|
|
|
|
Feb 10 2014, 21:04
|

Профессионал
    
Группа: Свой
Сообщений: 1 080
Регистрация: 16-11-04
Из: СПб
Пользователь №: 1 143

|
Цитата(SM @ Feb 10 2014, 19:52)  Что касается двух ResetEvent в двух тредах, так то понятно и без описания, что первый тред может сбросить event еще до того, как проснется второй. я исходил из того, что оба потока были в состоянии WAIT/SUSPEND в момент установки события events_t2_rdy шедуллер бы увидел список из двух ожидающих потоков и перевел оба в RUNNABLE. А уж дальше пофиг какой что сбросит Значит в винде не так P.S. Нашел кстати, откуда я вычитал, что одно событие может запускать несколько потоков Цитата Событие с ручным управлением подобно стартовому пистолету. Как только оно будет установлено в сигнализирующее состояние, будут освобождены сразу все потоки. ссылка
--------------------
Марс - единственная планета, полностью населенная роботами (около 7 штук).
|
|
|
|
|
Feb 10 2014, 21:17
|
Гуру
     
Группа: Свой
Сообщений: 7 946
Регистрация: 25-02-05
Из: Moscow, Russia
Пользователь №: 2 881

|
Цитата(megajohn @ Feb 11 2014, 01:04)  Значит в винде не так Она еще много может преподнести неприятных сюрпризов, если надеяться на какую-то, нигде официально не описанную, логику, которая "якобы должна бы быть такой". И вообще, не читайте по утрам советских газет... В MSDN английским по белому про SetEvent: The state of a manual-reset event object remains signaled until it is set explicitly to the nonsignaled state by the ResetEvent function. Any number of waiting threads, or threads that subsequently begin wait operations for the specified event object by calling one of the wait functions, can be released while the object's state is signaled.То есть ЛЮБОЕ КОЛИЧЕСТВО ожидающих тредов МОЖЕТ БЫТЬ запущено. А может и не быть, и вовсе не обязательно, что все... любое количество это любое... может и одна, а может и две, а может и ни одной, если слишком быстро его сбросить... Так что все там корректно работает и в рамках документации.
|
|
|
|
|
Feb 11 2014, 07:53
|

Профессионал
    
Группа: Свой
Сообщений: 1 080
Регистрация: 16-11-04
Из: СПб
Пользователь №: 1 143

|
Цитата(SM @ Feb 11 2014, 01:17)  То есть ЛЮБОЕ КОЛИЧЕСТВО ожидающих тредов МОЖЕТ БЫТЬ запущено. А может и не быть, и вовсе не обязательно, что все... любое количество это любое... может и одна чой-та я не согласен вообщем, методом проб и ошибок вроде понял в чем трабла. после освобождения t2 она так быстро делает todo и выставляет event_t2 что t1a просто не успевает дойти до ожидания, а другая t1b успевает и сбрасывает событие
Вообщем, сделал по вашему первому посту, работает и ладно UPD: проблема, в том что применена связка команд SetEvent( events_t1_rdy[0] ) и WaitForSingleObject( events_t2_rdy, 5000 ); и эта связка не атомарна. Тут напрашивается SignalObjectAndWait но оказывается, что тоже не атомарный =( UPD2: Цитата(SM @ Feb 10 2014, 19:52)  Что касается двух ResetEvent в двух тредах, так то понятно и без описания, что первый тред может сбросить event еще до того, как проснется второй. скорее всего, что первый тред может сбросить event еще до того, как уйдет в ожидание и уснёт второй.
--------------------
Марс - единственная планета, полностью населенная роботами (около 7 штук).
|
|
|
|
|
Feb 12 2014, 04:40
|
практикующий тех. волшебник
    
Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417

|
Цитата(megajohn @ Feb 11 2014, 11:53)  чой-та я не согласен... помогает восприятию, если воспринимать потоки как цепочку команд которая может быть вытеснена ядром на задворки щедуллера и быть вызвана через месяц, год, десять.... очень часто народ пишет например старт ниток без синхронной фазы. как следствие - при ударных нагрузках временные параметры текут. и конкретно текут. без фаз синхронизации логика расползается и перестаёт(как правило) корректно работать.
|
|
|
|
|
Feb 12 2014, 08:33
|

Профессионал
    
Группа: Свой
Сообщений: 1 080
Регистрация: 16-11-04
Из: СПб
Пользователь №: 1 143

|
Цитата(kolobok0 @ Feb 12 2014, 08:40)  очень часто народ пишет например старт ниток без синхронной фазы. как следствие - при ударных нагрузках временные параметры текут. и конкретно текут. без фаз синхронизации логика расползается и перестаёт(как правило) корректно работать. синхронизацю по запуску потоков применяю кстати, кому из начинающих хочется поигратся с потоками и эвентами, то вот готовый тестовый проектик
test_ev.rar ( 10.36 килобайт )
Кол-во скачиваний: 50
--------------------
Марс - единственная планета, полностью населенная роботами (около 7 штук).
|
|
|
|
|
Feb 12 2014, 12:51
|
практикующий тех. волшебник
    
Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417

|
Цитата(megajohn @ Feb 12 2014, 12:33)  ..синхронизацю по запуску потоков применяю... вот взять ваш пример... вы на нитке ждёте команды гоу. замечательно... а кто сказал что нитка готова???? ну т.е. дошла да этой точки и ждёт? больше скажу - забейте шедуллер оси с большим приоритетом и ага... у вас нитки будут стартовать ... ээээ да вообще могут не стартовать(когда то даже делал яркий пример, как можно "случайный генератор" чисел основанный на нитках делать совсем не случайный. потому, что именно не было синхронизации)... а вы уже получите отработку на майне свои секунды... ну и второе маленьчкое замечание.. если пишите на си плас плас - сделайте лаконичный и просто класс для порождения нитки. при грамотной упаковке решаться сразу такие вещи как передача различных по типу данных в нитку, вопросы синхронизации старт-стопа нитки, ну и кучка ышо плюшечек нароете по дороге... вот этот класец Вам многое поможет потом по жизни. поверьте реализация в библиотеках - всякие бусты и ко = не всегда ровная  ))
Сообщение отредактировал kolobok0 - Feb 12 2014, 12:54
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|