Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

WaitFor/Object

14
15 сентября 2009 года
Phodopus
3.3K / / 19.06.2008
Есть положим подобный код:
 
Код:
WaitForSingleObject(evt, INFINITE);
ResetEvent(evt);
WaitForSingleObject(evt, INFINITE);

выполняется кучей тредов (от 2х до бесконечности), и они все висят на 1й строке. Отдельный тред делает SetEvent(). Вчера возникли страшные сомнения (тупил наверное, сегодня они уже рассеялись но я задумал написать сюда, и напишу уже) что строка 2 в некоторых тредах (после SetEvent-а в управляющем) может не выполниться. Вообщем от вас требуется подтвердить безосновательность сомнений :).
5
15 сентября 2009 года
hardcase
4.5K / / 09.08.2005
Что-то не соображу. А зачем его сбрасывать в каждом потоке? Можно же использовать auto reset event. (т.е. CreateEventEx вызывать с флагом 0).



UPD Не подумал. При авторесете, будет "отпущен" только один поток...


UPD2: MSDN уверяет что любое количество потоков, вошедших в wait-функцию будут "отпущены"
[quote=MSDN]
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.
[/quote]
14
16 сентября 2009 года
Phodopus
3.3K / / 19.06.2008
Во, а помню что-то такое, но думал что это у Руссиновича написано, хотя лезть что туда, что в MSDN не было настроения :). Хотя смущает меня языковая конструкция
Цитата:

Any number ... can be released


Типа, может быть отпущено любое число тредов (а не то которое вы ожидаете). Да и вообще смущает "может".

Пожалуй разовью тему. Вообще требуется сделать следующее:
Есть код с циклом. Этот код выполняется кучей тредов. По окончанию итерации цикла каждый тред засыпает. Последний заснувший тред должен пробудить контрол-тред который воспользовавшись награбленным отпустит остальные треды на следующую итерацию и заснет сам. Я, по доброте душевной, начал решать эту задачу на семафорах (они вообщем-то для этого самое оно) но выяснилось (из теории - не проверял), что виндовские семафоры не могут принимать значения ниже 0. Почему мы имеем такой бред и где я видел "нормальные" семафоры - вопрос недели у меня (похоже то ли в unix, то ли в qnx) :). Теперь я сижу на ивентах и самостоятельно майнтэню счетчик. Вроде сносно, но ощущение пустоты не отпускает. Может я пропустил что-то в жизни?

5
16 сентября 2009 года
hardcase
4.5K / / 09.08.2005
Цитата: Phodopus
Теперь я сижу на ивентах и самостоятельно майнтэню счетчик. Вроде сносно, но ощущение пустоты не отпускает. Может я пропустил что-то в жизни?


На семафорах задача вполне решаема. Нужно просто при создании семафора задать количество потоков, управление которыми будет им контролироваться.

14
16 сентября 2009 года
Phodopus
3.3K / / 19.06.2008
Верно. Но семафор "сигналит", когда он все-что-угодно лишь бы не 0. А мне нужен объект который отпустят n тредов и он станет сигналящим.
5
16 сентября 2009 года
hardcase
4.5K / / 09.08.2005
Цитата: Phodopus
Верно. Но семафор "сигналит", когда он все-что-угодно лишь бы не 0. А мне нужен объект который отпустят n тредов и он станет сигналящим.

Если счетчик семафора имеет значение N,то он сможет отпустить N потоков.

5
16 сентября 2009 года
hardcase
4.5K / / 09.08.2005
Мастер-поток может ожидать завершения выполнения N рабочих потоков путем декремента второго семафора. Задача же вырождается в классику про поставщиков (1 штук - мастер поток) и потребителей (N штук рабочих потоков).
14
16 сентября 2009 года
Phodopus
3.3K / / 19.06.2008
Цитата: hardcase
Если счетчик семафора имеет значение N,то он сможет отпустить N потоков.


Ага. А мне из N потоков нужно отпускать 1. Отпускать N потоков из одного разумнее как-раз ивентом в моем случае (N - не конкретное а любое, и отпустить я должен не определенное кол-во, а всех).

Цитата: hardcase
Мастер-поток может ожидать завершения выполнения N рабочих потоков путем декремента второго семафора.


Пусть он декрементит 2й семафор, когда он примет значение 0 он должен ждать (вообще он должен создаться заблокированным, т.е. = 0). Теперь любой тред отпускающий семафор (до значения 1) отпустит мастер-тред, что недопустимо - мастер-тред должен освободиться последним еще работающим тредом, в общем случае любым.

5
16 сентября 2009 года
hardcase
4.5K / / 09.08.2005
Цитата: Phodopus
Ага. А мне из N потоков нужно отпускать 1. Отпускать N потоков из одного разумнее как-раз ивентом в моем случае (N - не конкретное а любое, и отпустить я должен не определенное кол-во, а всех).

Окей. Соглашусь.

Цитата: Phodopus

Пусть он декрементит 2й семафор, когда он примет значение 0 он должен ждать (вообще он должен создаться заблокированным, т.е. = 0). Теперь любой тред отпускающий семафор (до значения 1) отпустит мастер-тред, что недопустимо - мастер-тред должен освободиться последним еще работающим тредом, в общем случае любым.

Мастер поток должен знать сколько раз ему ждать сигнала
семафора. Т.е. знать количество потоков.

Вот примерный псевдокод:

Код:
event = CreateEvent(init = 0)

worker_ready = CreateSemaphore(init = 0, max = MAX(INT32))

master:
    for(i in [1..N])
        InitWorkerThread(i)
       
    loop {
        for(i in [1..N])
            WaitFor(worker_ready)


        SetEvent(event)
        ResetEvent(event)
     }




worker:
    DoSelfInit()
   
    Release(worker_ready)

    while(WaitFor(event))
       
        DoWork()
       
        Release(worker_ready)
    }
З.Ы. Всетаки мне не нравится event здесь. Семафор уместнее. Тем более что все равно приходится знать количество рабочих потоков.
14
16 сентября 2009 года
Phodopus
3.3K / / 19.06.2008
Прорабатывал я такой вариант. Честно говоря после "отрицательных" семафоров цикл с wait-ом мне показался феерическим. Наверное я не прав. Хотя блин, была б возможность создать семафор с -N+1 и заново устанавливать ему это значение в мастере перед отпусканием воркеров, неужели не комильфо? И никаких циклов.
Цитата:
З.Ы. Всетаки мне не нравится event здесь.


Дык мне тож не очень :). Ну ладно, теперь будем думать какой вариант выбрать с учетом уже накиданного на ивентах.
О! Вспомнил чем мне не нравится цикл - тупое N-1 раз абсолютно бессмысленное пробуждение мастер-треда. А это все-таки ресурсы, да и вапще. Зол на микрософт :).

5
16 сентября 2009 года
hardcase
4.5K / / 09.08.2005
Цитата: Phodopus

Дык мне тож не очень :). Ну ладно, теперь будем думать какой вариант выбрать с учетом уже накиданного на ивентах.

Зная количество потоков можно отпустить их все заклинанием Release, увелчив счетчик семафора ровно на N.

Если рабочие потоки выполняются достаточно длительно, то N-раз проснуться мастер-потоку будет практически ничего не стоить.

14
16 сентября 2009 года
Phodopus
3.3K / / 19.06.2008
Цитата: hardcase
Зная количество потоков можно отпустить их все заклинанием Release, увелчив счетчик семафора ровно на N.


Да, с этим никаких проблем.

Цитата: hardcase

Если рабочие потоки выполняются достаточно длительно, то N-раз проснуться мастер-потоку будет практически ничего не стоить.


Ну блин, он будет N-1 раз пробуждаться чтобы сделать i++ !! Мне жалко планировщик потоков :D. По моему это ахтунг.

5
17 сентября 2009 года
hardcase
4.5K / / 09.08.2005
Цитата: Phodopus
Ну блин, он будет N-1 раз пробуждаться чтобы сделать i++ !! Мне жалко планировщик потоков :D. По моему это ахтунг.


Сейчас полазил по MSDN, в принципе можно воспользоваться Thread Pool API, доступным начиная с Windows Vista. К примеру, WaitForThreadpoolWaitCallbacks ожидает пока завершатся все колбэки пула.

260
17 сентября 2009 года
Ramon
1.1K / / 16.08.2003
Разрешите поинтересоваться, а какова постановка задачи вообще, а не игра с потоками в частности?
14
17 сентября 2009 года
Phodopus
3.3K / / 19.06.2008
я уже писал
Цитата:

Есть код с циклом. Этот код выполняется кучей тредов. По окончанию итерации цикла каждый тред засыпает. Последний заснувший тред должен пробудить контрол-тред который воспользовавшись награбленным отпустит остальные треды на следующую итерацию и заснет сам.


Цитата:

Thread Pool API, доступным начиная с Windows Vista. К примеру, WaitForThreadpoolWaitCallbacks ожидает пока завершатся все колбэки пула.


ух ты блин :). Интересно. Но правда нам до висты далеко.

260
17 сентября 2009 года
Ramon
1.1K / / 16.08.2003
Код:
LONG uMaxThreads = X;

for (;;)
{
    DataCollecting();


    if ( InterlockedDecrement(&uMaxThreads) )
    {
        WaitForSingleObject(...);
    }
    else
    {
        DataProceessing();

        uMaxThreads = X;
   
        PulseEvent(...);
    }
}


Развлекайтесь.

PS: Событие с мануальным сбросом
14
17 сентября 2009 года
Phodopus
3.3K / / 19.06.2008
Не стал вникать в ваш код (а вы во все мною до этого написанное) но что-то очень похожее как-раз сделано и пока работает. А хочу семафорами блин и по-умному! :)
260
17 сентября 2009 года
Ramon
1.1K / / 16.08.2003
А у меня наличествуют сомнения, что вы правильно подходите к решению задачи.
14
17 сентября 2009 года
Phodopus
3.3K / / 19.06.2008
Тоесть вы считаете что ивенты - самое то?
14
29 октября 2009 года
Phodopus
3.3K / / 19.06.2008
Цитата: Phodopus
Есть положим подобный код:
выполняется кучей тредов (от 2х до бесконечности), и они все висят на 1й строке. Отдельный тред делает SetEvent(). Возникли страшные сомнения что строка 2 в некоторых тредах (после SetEvent-а в управляющем) может не выполниться.


Кстати. Отвечу сам на свой же вопрос: :)
Сомнения оказались абсолютно обоснованными, действительно возможна ситуация когда все кроме 1 треда уснут на проснувшись. Надо будет найти время пробежаться по Рихтеру/Руссиновичу за поиском точного механизма работы планировщика. Найду техническое объяснение - добавлю.
[COLOR="Gray"]Если второй строчкой вставить Sleep(0) можно видеть что все потоки действительно пробуждаются.[/COLOR]

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог