Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

wait functions


Страницы:   1 2 3

Polevi ©   (2006-02-01 12:09:00) 

несколько потоков ждут семафор
насколько возможно предсказать в каком порядке потоки проснуться при вызове ReleaseSemaphore ?
FIFO, LIFO или случайным образом ?

у меня есть пул потоков который обслуживает запросы клиентов
пул наращиваемый, алгоритм удаления потока следующий - он удаляется если ждет объекта более 1 минуты к примеру
я опасаюсь что данный алгоритм не будет работать если потоки будут получать управление в порядке вызова ими Wait ф-ии, в моем случае они будут получать управление по очереди даже если будет только один клиент

какие будут соображения, господа ?


Digitman   (2006-02-01 16:15:00) [21]


> Polevi ©   (01.02.06 15:59) [26]
> RS вызывает транспортный поток


Тогда поясни, какое дело логике транспортного потока до логики потока-диспетчера пула ?


Игорь Шевченко   (2006-02-01 16:15:00) [22]


> но поскольку работает механизм FIFO на каждый васин запрос
> будет просыпаться следующий поток, и таймаута ни один из
> них не дождется


Я вот этого момента честно не понимаю, почему ни один не дождется таймаута ?


Polevi   (2006-02-01 16:02:00) [23]

этот код я привел чтобы показать что после добавления нового потока он обрабатывает запрос и не уничтожается


Polevi   (2006-02-01 16:01:00) [24]

>Rouse_ ©   (01.02.06 15:53) [24]
ну и чем твоя логика отличается от моей интересно

procedure TWorkThread.Execute;
var
 arr:array[0..1] of THandle;
 ir:TInvokeRequest;
 res:TMemoryStream;
 client:TClient;
begin
 arr[0]:=FWaitDataSem;
 arr[1]:=FStopEvent;
 CoInitialize(nil);
 while not Terminated do
 begin
   case WaitForMultipleObjects(2,@arr[0],false,WORKTHREAD_TIMEOUT) of
     WAIT_OBJECT_0: //request
     begin
       ir:=FReqResQueue.GetRequest(client);
       try
         try
           res:=ir.Invoke;
         except on E:Exception do
           res:=CreateExceptionResponse(E.Message);
         end;
         FReqResQueue.AddResponse(client,res);
       finally
         ir.Free;
       end
     end;
     WAIT_TIMEOUT:
     begin
       if FThreadPool.Remove(self) then Terminate;
     end;
     WAIT_OBJECT_0+1: //stop
     begin
       Terminate;
     end
   end;
 end;
 CoUninitialize;
end;


Polevi   (2006-02-01 15:59:00) [25]

>Digitman ©   (01.02.06 15:46) [23]
ты не в теме, RS вызывает транспортный поток


Polevi   (2006-02-01 15:57:00) [26]

попытаюсь обяснить еще раз что мне надо
у меня наращиваемый пул
необходимо определить условия при которых в него добалвяются и удаляются потоки
алгоритм добавления таков - специальный watch поток следит за очередью клиентских запросов и если находит запрос который лежит там больше X - он добавляет поток в пул
алгоритм удаления был мной сформулирован след. образом - рабочий поток пытается дождаться запроса время Y и если не дожидается - просыпается по таймауту и поняв что делать ему нефиг удаляет себя из пула
допустим в час пик колво потоков достигло 20 а затем пробили куранты все пошли обедать кроме трудоголика васи
вася старательно помылает серверу запросы
вася один а потоков 20
но поскольку работает механизм FIFO на каждый васин запрос будет просыпаться следующий поток, и таймаута ни один из них не дождется

вообщем нужен другой механизм необходимости удаления потока из пула, WAIT_TIMEOUT не подходит


Rouse_   (2006-02-01 15:53:00) [27]

Может изменить логику?

1. Пришел запрос - свободных потоков нет - делаем новый, он запрашивает данные и начинает работать.
2. Поток отработал - ставим его на WaitXX (..., INFINITE);
3. Пришел запрос - делаем ReleaseSemaphore. Проснувшийся поток спрашивает свои данные и начинает их выполнять...
Если никто не проснулся, то пункт 1.


Digitman   (2006-02-01 15:46:00) [28]


> Polevi ©   (01.02.06 15:32) [18]
> >Digitman ©   (01.02.06 15:29) [16]
> этот параметр равен колву клиентских запросов в очереди


Тогда вопрос - нашута обрабатывающему некий запрос потоку знать состояние очереди ? Не его это дело ..


Игорь Шевченко   (2006-02-01 15:45:00) [29]

Polevi ©   (01.02.06 15:41) [21]

Тебе хочется, чтобы на новый запрос просыпался поток, который последним обрабатывал клиентский запрос ? Ты извини за расспросы, я просто понять пытаюсь до конца.


Polevi   (2006-02-01 15:41:00) [30]

>Игорь Шевченко ©   (01.02.06 15:34) [20]
он его дождется если не будет больше запросов
собственно моя проблема в том, что если один клиент будет каждую секунду посылать запрос - за минуту последовательно проснуться 60 потоков с WAIT_OBJECT_0, до WAIT_TIMEOUT дело не дойдет
вот в случае с LIFO каждый раз бы просыпался поток который посденим вызвал Wait ф-ию а остальные 59 дождались бы таймаута и уничтожились


Игорь Шевченко   (2006-02-01 15:34:00) [31]

Polevi ©   (01.02.06 15:13) [14]


> оставшиеся потоки ждут след. вызова RS


Или таймаута ?

Я наверное не до конца понимаю, извини

Два рабочих потока ждут освобождения семафора с таймаутом.

Третий поток освободил семафор с ReleaseCount равным единице. Один из потоков проснулся с WAIT_OBJECT_0. Другой поток дождется таймаута ?


Rouse_   (2006-02-01 15:33:00) [32]

А, ну собственно > Polevi ©   (01.02.06 15:13) [14]сам все рассказал :)


Polevi   (2006-02-01 15:32:00) [33]

>Digitman ©   (01.02.06 15:29) [16]
этот параметр равен колву клиентских запросов в очереди


Rouse_   (2006-02-01 15:32:00) [34]


> А не представляю я другое - каким образом кол-во "пробуждаемых"
> тобой потоков зависит от параметра lReleaseCount ф-ции ReleaseSemaphore()
> ..

По всей видимости у него сделано по такому принципу:

program Project1;

uses
 Windows, Messages, SysUtils, gssocket;

const
 THREAD_COUNT = 4;

var
 hSemaphore: THandle;
 hThread: array [0..THREAD_COUNT - 1] of THandle;
 lpThreadId, lpPreviousCount: DWORD;
 I: Integer;

procedure ThreadProc(lpParameter: Pointer); stdcall;
var
 hThreadSemaphore: THandle;
begin
 case WaitForSingleObject(hSemaphore, 100000) of
   WAIT_OBJECT_0:
     MessageBox(0, PChar('WAIT_OBJECT_0: ' + IntToStr(Integer(lpParameter))), nil, MB_OK);
   WAIT_FAILED:
     MessageBox(0, PChar('WAIT_FAILED: ' + IntToStr(Integer(lpParameter))), nil, MB_OK);
   WAIT_TIMEOUT:
     MessageBox(0, PChar('WAIT_TIMEOUT: ' + IntToStr(Integer(lpParameter))), nil, MB_OK);
 end;
end;

begin
 hSemaphore := CreateSemaphore(nil, 0, THREAD_COUNT, 'TestThreadSemaphore');
 if hSemaphore = 0 then
   RaiseLastOSError;
 for I := 0 to THREAD_COUNT - 1 do
   hThread[I] := CreateThread(nil, 0, @ThreadProc, Pointer(I), 0, lpThreadId);
 lpPreviousCount := THREAD_COUNT;
 Sleep(1000);
 if not ReleaseSemaphore(hSemaphore, 1, @lpPreviousCount) then
   RaiseLastOSError;
 Sleep(2000);
 if not ReleaseSemaphore(hSemaphore, 2, @lpPreviousCount) then
   RaiseLastOSError;
 Sleep(2000);
 if not ReleaseSemaphore(hSemaphore, 1, @lpPreviousCount) then
   RaiseLastOSError;
 Sleep(2000);
end.


Тут наглядно видно. Создается 4 потока. 1 потока отпускаеться через секунду. Потом отпускаються еще два и потом еще один.

Кол-во потоков варьируеться в ReleaseSemaphore


Digitman   (2006-02-01 15:29:00) [35]


> Polevi ©   (01.02.06 15:13) [14]


Спасибо. Это понятно.

Но непонятна твоя прикладная логика, относящаяся к "вызвал RS с параметром 2".

Почему не 3 ? Или не 1 ? Это же важно, согласись..


Eraser   (2006-02-01 15:17:00) [36]

по-моему по теме
Тут возникает интересный вопрос. Если несколько потоков ждет один объект ядра, какой из них пробудится при освобождении этого объекта? Официально Microsoft отвечает на этот вопрос так: "Алгоритм действует честно" Что это за алгоритм, Micro soft не говорит, потому что нс хочст связывать себя обязательствами всегда придер живаться именно этого алгоритма. Она утверждает лишь одно- если объект ожидает ся несколькими потоками, то всякий раз, когда этот объект переходит в свободное состояние, каждый из них получает шанс на пробуждение.

Таким образом, приоритет потока не имеет значения- поток с самым высоким приоритетом не обязательно первым захватит объект. Не получает преимущества и поток, который ждал дольше всех. Есть даже вероятность, что какой-то поток сумеет повторно захватить объект. Конечно, это было бы нечестно по отношению к другим потокам, и алгоритм пытается не допустить этого. Но никаких гарантий нет.

Рихтер


Polevi   (2006-02-01 15:13:00) [37]

напрямую зависит
счетчик=0
10 wait ф-ий ждут пока засигналит объект
я вызвал RS с параметром 2
объект засигналил
в 1 потоке ф-ия возвратила управление уменьшив значение на 1
счетчик =1
объект продолжает сигналить
в 2потоке ф-ия возвратила управление уменьшив значение на 1
счетчик =0
объект не сигналит
оставшиеся потоки ждут след. вызова RS


Digitman   (2006-02-01 15:09:00) [38]


> Polevi ©   (01.02.06 15:00) [12]


> странно что я должен вам это обяъснять


Работу ф-ции мне не надо объяснять - я ее достаточно четко себе представляю.

А не представляю я другое - каким образом кол-во "пробуждаемых" тобой потоков зависит от параметра lReleaseCount ф-ции ReleaseSemaphore() ..


Polevi   (2006-02-01 15:00:00) [39]

The ReleaseSemaphore function increases the count of the specified semaphore object by a specified amount.
The state of a semaphore object is signaled when its count is greater than zero and nonsignaled when its count is equal to zero.

каждая ожидающая Wait ф-ия умньшит значение счетчика на 1
когда its count is equal to zero. потоки прекратят свое просыпание

странно что я должен вам это обяъснять если честно


Digitman   (2006-02-01 14:34:00) [40]


> проснется столько сколько я укажу в ReleaseSemaphore


здесь, пожалуйста. подробнее ..


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо