| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363 | 
							- unit CompThread;
 
- interface
 
- {$WARN SYMBOL_DEPRECATED OFF}
 
- {$WARN SYMBOL_PLATFORM OFF}
 
- uses
 
-   Classes, Windows;
 
- type
 
- { TCompThread }
 
-   TCompThread = class
 
-   private
 
-     FHandle: THandle;
 
-     FThreadID: TThreadID;
 
-     FTerminated: Boolean;
 
-     FSuspended: Boolean;
 
-     FFreeOnTerminate: Boolean;
 
-     FFinished: Boolean;
 
-     FReturnValue: Integer;
 
-     FOnTerminate: TNotifyEvent;
 
-     FMethod: TThreadMethod;
 
-     FSynchronizeException: TObject;
 
-     procedure CallOnTerminate;
 
-     function GetPriority: TThreadPriority;
 
-     procedure SetPriority(Value: TThreadPriority);
 
-     procedure SetSuspended(Value: Boolean);
 
-   protected
 
-     procedure DoTerminate; virtual;
 
-     procedure Execute; virtual; abstract;
 
-     procedure Synchronize(Method: TThreadMethod);
 
-     property ReturnValue: Integer read FReturnValue write FReturnValue;
 
-     property Terminated: Boolean read FTerminated;
 
-   public
 
-     constructor Create(CreateSuspended: Boolean);
 
-     destructor Destroy; override;
 
-     procedure Resume;
 
-     procedure Suspend;
 
-     procedure Terminate; virtual;
 
-     function WaitFor(Milliseconds: Cardinal = INFINITE): Boolean;
 
-     property FreeOnTerminate: Boolean read FFreeOnTerminate write FFreeOnTerminate;
 
-     property Handle: THandle read FHandle;
 
-     property Priority: TThreadPriority read GetPriority write SetPriority;
 
-     property Suspended: Boolean read FSuspended write SetSuspended;
 
-     property ThreadID: TThreadID read FThreadID;
 
-     property OnTerminate: TNotifyEvent read FOnTerminate write FOnTerminate;
 
-   end;
 
- implementation
 
- uses
 
-   SysUtils, DateUtils;
 
- const
 
-   CM_EXECPROC = $8FFF;
 
-   CM_DESTROYWINDOW = $8FFE;
 
- type
 
-   PRaiseFrame = ^TRaiseFrame;
 
-   TRaiseFrame = record
 
-     NextRaise: PRaiseFrame;
 
-     ExceptAddr: Pointer;
 
-     ExceptObject: TObject;
 
-     ExceptionRecord: PExceptionRecord;
 
-   end;
 
- var
 
-   ThreadLock: TRTLCriticalSection;
 
-   ThreadWindow: HWND;
 
-   ThreadCount: Integer;
 
- procedure FreeThreadWindow;
 
- begin
 
-   if ThreadWindow <> 0 then
 
-   begin
 
-     DestroyWindow(ThreadWindow);
 
-     ThreadWindow := 0;
 
-   end;
 
- end;
 
- function ThreadWndProc(Window: HWND; Message, wParam, lParam: Longint): Longint; stdcall;
 
- begin
 
-   case Message of
 
-     CM_EXECPROC:
 
-       with TCompThread(lParam) do
 
-       begin
 
-         Result := 0;
 
-         try
 
-           FSynchronizeException := nil;
 
-           FMethod;
 
-         except
 
-           FSynchronizeException := AcquireExceptionObject;
 
-         end;
 
-       end;
 
-     CM_DESTROYWINDOW:
 
-       begin
 
-         EnterCriticalSection(ThreadLock);
 
-         try
 
-           Dec(ThreadCount);
 
-           if ThreadCount = 0 then
 
-             FreeThreadWindow;
 
-         finally
 
-           LeaveCriticalSection(ThreadLock);
 
-         end;
 
-         Result := 0;
 
-       end;
 
-   else
 
-     Result := DefWindowProc(Window, Message, wParam, lParam);
 
-   end;
 
- end;
 
- var
 
-   ThreadWindowClass: TWndClass = (
 
-     style: 0;
 
-     lpfnWndProc: @ThreadWndProc;
 
-     cbClsExtra: 0;
 
-     cbWndExtra: 0;
 
-     hInstance: 0;
 
-     hIcon: 0;
 
-     hCursor: 0;
 
-     hbrBackground: 0;
 
-     lpszMenuName: nil;
 
-     lpszClassName: 'TThreadWindow');
 
- procedure AddThread;
 
-   function AllocateWindow: HWND;
 
-   var
 
-     TempClass: TWndClass;
 
-     ClassRegistered: Boolean;
 
-   begin
 
-     ThreadWindowClass.hInstance := HInstance;
 
-     ClassRegistered := GetClassInfo(HInstance, ThreadWindowClass.lpszClassName,
 
-       TempClass);
 
-     if not ClassRegistered or (TempClass.lpfnWndProc <> @ThreadWndProc) then
 
-     begin
 
-       if ClassRegistered then
 
-         Windows.UnregisterClass(ThreadWindowClass.lpszClassName, HInstance);
 
-       Windows.RegisterClass(ThreadWindowClass);
 
-     end;
 
-     Result := CreateWindow(ThreadWindowClass.lpszClassName, '', 0,
 
-       0, 0, 0, 0, 0, 0, HInstance, nil);
 
-   end;
 
- begin
 
-   EnterCriticalSection(ThreadLock);
 
-   try
 
-     if ThreadCount = 0 then
 
-       ThreadWindow := AllocateWindow;
 
-     Inc(ThreadCount);
 
-   finally
 
-     LeaveCriticalSection(ThreadLock);
 
-   end;
 
- end;
 
- procedure RemoveThread;
 
- begin
 
-   EnterCriticalSection(ThreadLock);
 
-   try
 
-     if ThreadCount = 1 then
 
-       PostMessage(ThreadWindow, CM_DESTROYWINDOW, 0, 0);
 
-   finally
 
-     LeaveCriticalSection(ThreadLock);
 
-   end;
 
- end;
 
- {type
 
-   PThreadRec = ^TThreadRec;
 
-   TThreadRec = record
 
-     Func: TThreadFunc;
 
-     Parameter: Pointer;
 
-   end;
 
- function ThreadWrapper(Parameter: Pointer): Integer; stdcall;
 
- asm
 
-         CALL    _FpuInit
 
-         XOR     ECX,ECX
 
-         PUSH    EBP
 
-         PUSH    offset _ExceptionHandler
 
-         MOV     EDX,FS:[ECX]
 
-         PUSH    EDX
 
-         MOV     EAX,Parameter
 
-         MOV     FS:[ECX],ESP
 
-         MOV     ECX,[EAX].TThreadRec.Parameter
 
-         MOV     EDX,[EAX].TThreadRec.Func
 
-         PUSH    ECX
 
-         PUSH    EDX
 
-         CALL    _FreeMem
 
-         POP     EDX
 
-         POP     EAX
 
-         CALL    EDX
 
-         XOR     EDX,EDX
 
-         POP     ECX
 
-         MOV     FS:[EDX],ECX
 
-         POP     ECX
 
-         POP     EBP
 
- end;
 
- function BeginThread(SecurityAttributes: Pointer; StackSize: LongWord;
 
-   ThreadFunc: TThreadFunc; Parameter: Pointer; CreationFlags: LongWord;
 
-   var ThreadId: LongWord): Integer;
 
- var
 
-   P: PThreadRec;
 
- begin
 
-   New(P);
 
-   P.Func := ThreadFunc;
 
-   P.Parameter := Parameter;
 
-   IsMultiThread := TRUE;
 
-   Result := CreateThread(SecurityAttributes, StackSize, @ThreadWrapper, P,
 
-     CreationFlags, ThreadID);
 
- end;
 
- procedure EndThread(ExitCode: Integer);
 
- begin
 
-   ExitThread(ExitCode);
 
- end;
 
- }
 
- { TCompThread }
 
- function ThreadProc(Thread: TCompThread): Integer;
 
- var
 
-   FreeThread: Boolean;
 
- begin
 
-   try
 
-     Thread.Execute;
 
-   finally
 
-     FreeThread := Thread.FFreeOnTerminate;
 
-     Result := Thread.FReturnValue;
 
-     Thread.FFinished := True;
 
-     Thread.DoTerminate;
 
-     if FreeThread then
 
-     begin
 
-       Thread.Free;
 
-     end;
 
-     EndThread(Result);
 
-     // it should not get past EndThread
 
-   end;
 
- end;
 
- constructor TCompThread.Create(CreateSuspended: Boolean);
 
- var
 
-   Flags: Cardinal; //DWORD;
 
- begin
 
-   inherited Create;
 
-   AddThread;
 
-   FSuspended := CreateSuspended;
 
-   Flags := 0;
 
-   if CreateSuspended then Flags := CREATE_SUSPENDED;
 
-   FHandle := BeginThread(nil, 0, @ThreadProc, Pointer(Self), Flags, FThreadID);
 
- end;
 
- destructor TCompThread.Destroy;
 
- begin
 
-   if not FFinished and not Suspended then
 
-   begin
 
-     Terminate;
 
-     WaitFor;
 
-   end;
 
-   if FHandle <> 0 then CloseHandle(FHandle);
 
-   inherited Destroy;
 
-   RemoveThread;
 
- end;
 
- procedure TCompThread.CallOnTerminate;
 
- begin
 
-   if Assigned(FOnTerminate) then FOnTerminate(Self);
 
- end;
 
- procedure TCompThread.DoTerminate;
 
- begin
 
-   if Assigned(FOnTerminate) then Synchronize(CallOnTerminate);
 
- end;
 
- const
 
-   Priorities: array [TThreadPriority] of Integer =
 
-    (THREAD_PRIORITY_IDLE, THREAD_PRIORITY_LOWEST, THREAD_PRIORITY_BELOW_NORMAL,
 
-     THREAD_PRIORITY_NORMAL, THREAD_PRIORITY_ABOVE_NORMAL,
 
-     THREAD_PRIORITY_HIGHEST, THREAD_PRIORITY_TIME_CRITICAL);
 
- function TCompThread.GetPriority: TThreadPriority;
 
- var
 
-   P: Integer;
 
-   I: TThreadPriority;
 
- begin
 
-   P := GetThreadPriority(FHandle);
 
-   Result := tpNormal;
 
-   for I := Low(TThreadPriority) to High(TThreadPriority) do
 
-     if Priorities[I] = P then Result := I;
 
- end;
 
- procedure TCompThread.SetPriority(Value: TThreadPriority);
 
- begin
 
-   SetThreadPriority(FHandle, Priorities[Value]);
 
- end;
 
- procedure TCompThread.Synchronize(Method: TThreadMethod);
 
- begin
 
-   FSynchronizeException := nil;
 
-   FMethod := Method;
 
-   SendMessage(ThreadWindow, CM_EXECPROC, 0, Longint(Self));
 
-   if Assigned(FSynchronizeException) then raise FSynchronizeException;
 
- end;
 
- procedure TCompThread.SetSuspended(Value: Boolean);
 
- begin
 
-   if Value <> FSuspended then
 
-     if Value then
 
-       Suspend else
 
-       Resume;
 
- end;
 
- procedure TCompThread.Suspend;
 
- begin
 
-   FSuspended := True;
 
-   SuspendThread(FHandle);
 
- end;
 
- procedure TCompThread.Resume;
 
- begin
 
-   if ResumeThread(FHandle) = 1 then FSuspended := False;
 
- end;
 
- procedure TCompThread.Terminate;
 
- begin
 
-   FTerminated := True;
 
- end;
 
- function TCompThread.WaitFor(Milliseconds: Cardinal): Boolean;
 
- var
 
-   Msg: TMsg;
 
-   H: THandle;
 
-   Start: TDateTime;
 
-   R: DWORD;
 
- begin
 
-   H := FHandle;
 
-   if GetCurrentThreadID = MainThreadID then
 
-   begin
 
-     Start := Now;
 
-     repeat
 
-       R := MsgWaitForMultipleObjects(1, H, False, Milliseconds, QS_SENDMESSAGE);
 
-       if R = WAIT_OBJECT_0 + 1 then PeekMessage(Msg, 0, 0, 0, PM_NOREMOVE)
 
-     until (R <> WAIT_OBJECT_0 + 1) or ((Milliseconds <> INFINITE) and (MilliSecondsBetween(Now, Start) >= Milliseconds));
 
-   end
 
-     else
 
-   begin
 
-     R := WaitForSingleObject(H, Milliseconds);
 
-   end;
 
-   Result := (R = WAIT_OBJECT_0);
 
- end;
 
- initialization
 
-   InitializeCriticalSection(ThreadLock);
 
- finalization
 
-   DeleteCriticalSection(ThreadLock);
 
- end.
 
 
  |