| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- { $HDR$}
- {**********************************************************************}
- { Unit archived using Team Coherence }
- { Team Coherence is Copyright 2002 by Quality Software Components }
- { }
- { For further information / comments, visit our WEB site at }
- { http://www.TeamCoherence.com }
- {**********************************************************************}
- {}
- { $Log: 10383: IdThreadMgrPool.pas
- {
- { Rev 1.0 2002.11.12 10:56:22 PM czhower
- }
- {
- 2002-06-23 -Andrew P.Rybin
- -2 deadlock fix (and also in IdThread)
- }
- unit IdThreadMgrPool;
- interface
- uses
- Classes,
- IdThread, IdThreadMgr;
- type
- TIdThreadMgrPool = class(TIdThreadMgr)
- protected
- FPoolSize: Integer;
- FThreadPool: TThreadList;
- //
- procedure ThreadStopped(AThread: TIdThread);
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- function GetThread: TIdThread; override;
- procedure ReleaseThread(AThread: TIdThread); override;
- procedure TerminateThreads; override;
- published
- property PoolSize: Integer read FPoolSize write FPoolSize default 0;
- End;
- implementation
- uses
- IdGlobal,
- SysUtils;
- { TIdThreadMgrPool }
- constructor TIdThreadMgrPool.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FThreadPool := TThreadList.Create;
- end;
- destructor TIdThreadMgrPool.Destroy;
- var
- i: integer;
- LThreads: TList;
- begin
- FPoolSize := 0;
- LThreads := FThreadPool.LockList;
- try
- for i:=0 to LThreads.Count-1 do begin
- with TIdThread(LThreads[i]) do begin
- //thread can use ComponentStreamSystem, we must prevent deadlock
- //Best way for IdUser's: calling TcpServer.Active:=FALSE & TerminateThreads from OnDestroy
- FreeOnTerminate := TRUE;
- Terminate;
- Start;
- end;//with
- end;
- finally FThreadPool.UnlockList; end;
- FreeAndNil(FThreadPool);
- inherited Destroy;
- end;
- function TIdThreadMgrPool.GetThread: TIdThread;
- var
- LThreadPool: TList;
- begin
- LThreadPool := FThreadPool.LockList;
- try
- if LThreadPool.Count > 0 then begin
- Result := TIdThread(LThreadPool[0]);
- LThreadPool.Delete(0);
- end else begin
- Result := CreateNewThread;
- Result.StopMode := smSuspend;
- end;
- finally FThreadPool.UnlockList; end;
- ActiveThreads.Add(Result);
- end;
- procedure TIdThreadMgrPool.ReleaseThread(AThread: TIdThread);
- var
- LThreadPool: TList;
- begin
- with ActiveThreads.LockList do try // To avoid ReleaseThread-code is
- if IndexOf(AThread)=-1 then exit; // executed multiple times, because
- finally // AThread.Free call ReleaseThread
- ActiveThreads.UnlockList; // again. Now we will detect the 2nd
- end; // time, and jump out of the routine
- ActiveThreads.Remove(AThread); // here.
- LThreadPool := FThreadPool.LockList;
- try
- // PoolSize = 0 means that we will keep all active threads in the thread pool
- if ((PoolSize > 0) and (LThreadPool.Count >= PoolSize))
- or AThread.Terminated or AThread.Suspended then begin
- AThread.OnStopped := NIL;
- AThread.FreeOnTerminate := TRUE;
- AThread.Terminate;
- AThread.Start;//if suspended
- end
- else begin
- AThread.OnStopped := ThreadStopped;
- AThread.Stop;//go sleep
- end;
- finally FThreadPool.UnlockList; end;
- End;//ReleaseThread
- procedure TIdThreadMgrPool.TerminateThreads;
- begin
- inherited TerminateThreads;
- with FThreadPool.LockList do
- try
- while Count > 0 do begin
- with TIdThread(Items[0]) do begin
- FreeOnTerminate := TRUE;
- Terminate;
- Start; //Stopped==TRUE because Terminated
- end;//with
- Delete(0);
- end;
- finally
- FThreadPool.UnlockList;
- end;
- end;
- procedure TIdThreadMgrPool.ThreadStopped(AThread: TIdThread);
- begin
- AThread.OnStopped := NIL; //work is done. prevent from unexpected usage
- if Assigned(FThreadPool) and NOT AThread.Terminated then begin
- FThreadPool.Add(AThread);
- end
- else begin
- AThread.Terminate; //abnormal situation: application termination or what?
- end;
- end;
- end.
|