123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- { Thread management routines }
- const
- CM_EXECPROC = $8FFF;
- CM_DESTROYWINDOW = $8FFE;
- type
- PRaiseFrame = ^TRaiseFrame;
- TRaiseFrame = record
- NextRaise: PRaiseFrame;
- ExceptAddr: Pointer;
- ExceptObject: TObject;
- ExceptionRecord: pointer; {PExceptionRecord}
- end;
- var
- ThreadWindow: HWND;
- ThreadCount: Integer;
- { event that happens when gui thread is done executing the method
- }
- ExecuteEvent: PRtlEvent;
- { guard for synchronization variables }
- SynchronizeCritSect: TRtlCriticalSection;
- { method to execute }
- SynchronizeMethod: TThreadMethod;
- { caught exception in gui thread, to be raised in calling thread }
- SynchronizeException: Exception;
- function ThreadWndProc(Window: HWnd; AMessage:UInt; WParam : WParam; LParam: LParam): Longint; stdcall;
- begin
- case AMessage of
- CM_EXECPROC:
- with TThread(lParam) do
- begin
- Result := 0;
- try
- FSynchronizeException := nil;
- FMethod;
- except
- { if RaiseList <> nil then
- begin
- FSynchronizeException := PRaiseFrame(RaiseList)^.ExceptObject;
- PRaiseFrame(RaiseList)^.ExceptObject := nil;
- end; }
- end;
- end;
- CM_DESTROYWINDOW:
- begin
- DestroyWindow(Window);
- Result := 0;
- end;
- else
- Result := DefWindowProc(Window, AMessage, wParam, lParam);
- end;
- end;
- const
- ThreadWindowClass: TWndClass = (
- style: 0;
- lpfnWndProc: nil;
- 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;
- ThreadWindowClass.lpfnWndProc:=WndProc(@ThreadWndProc);
- ClassRegistered := GetClassInfo(HInstance, ThreadWindowClass.lpszClassName,
- @TempClass);
- if not ClassRegistered or (TempClass.lpfnWndProc <> WndProc(@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
- if ThreadCount = 0 then
- ThreadWindow := AllocateWindow;
- Inc(ThreadCount);
- end;
- procedure RemoveThread;
- begin
- Dec(ThreadCount);
- if ThreadCount = 0 then
- PostMessage(ThreadWindow, CM_DESTROYWINDOW, 0, 0);
- end;
- { TThread }
- function ThreadProc(ThreadObjPtr: Pointer): Integer;
- var
- FreeThread: Boolean;
- Thread: TThread absolute ThreadObjPtr;
- begin
- try
- Thread.Execute;
- except
- Thread.FFatalException := TObject(AcquireExceptionObject);
- end;
- FreeThread := Thread.FFreeOnTerminate;
- Result := Thread.FReturnValue;
- Thread.FFinished := True;
- Thread.DoTerminate;
- if FreeThread then Thread.Free;
- end;
- constructor TThread.Create(CreateSuspended: Boolean);
- var
- Flags: Integer;
- begin
- inherited Create;
- AddThread;
- FSuspended := CreateSuspended;
- Flags := 0;
- if CreateSuspended then Flags := CREATE_SUSPENDED;
- FHandle := BeginThread(nil, 0, @ThreadProc, pointer(self), Flags, FThreadID);
- FFatalException := nil;
- end;
- destructor TThread.Destroy;
- begin
- if not FFinished and not Suspended then
- begin
- Terminate;
- WaitFor;
- end;
- if FHandle <> 0 then CloseHandle(FHandle);
- FFatalException.Free;
- FFatalException := nil;
- inherited Destroy;
- RemoveThread;
- end;
- procedure TThread.CallOnTerminate;
- begin
- FOnTerminate(Self);
- end;
- procedure TThread.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 TThread.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 TThread.SetPriority(Value: TThreadPriority);
- begin
- SetThreadPriority(FHandle, Priorities[Value]);
- end;
- procedure TThread.SetSuspended(Value: Boolean);
- begin
- if Value <> FSuspended then
- if Value then
- Suspend else
- Resume;
- end;
- procedure TThread.Suspend;
- begin
- FSuspended := True;
- SuspendThread(FHandle);
- end;
- procedure TThread.Resume;
- begin
- if ResumeThread(FHandle) = 1 then FSuspended := False;
- end;
- procedure TThread.Terminate;
- begin
- FTerminated := True;
- end;
- function TThread.WaitFor: Integer;
- var
- Msg: TMsg;
- begin
- if GetCurrentThreadID = MainThreadID then
- while MsgWaitForMultipleObjects(1, FHandle, False, INFINITE, QS_SENDMESSAGE) = WAIT_OBJECT_0 + 1 do
- PeekMessage(Msg, 0, 0, 0, PM_NOREMOVE)
- else
- WaitForSingleObject(ulong(FHandle), INFINITE);
- GetExitCodeThread(FHandle, DWord(Result));
- end;
- {
- $Log$
- Revision 1.7 2005-02-25 21:41:09 florian
- * generic tthread.synchronize
- * delphi compatible wakemainthread
- Revision 1.6 2005/02/14 17:13:32 peter
- * truncate log
- Revision 1.5 2005/02/06 13:06:20 peter
- * moved file and dir functions to sysfile/sysdir
- * win32 thread in systemunit
- }
|