fpc/rtl/win/tthread.inc
svenbarth bd7cc36ea6 The documentation says that a "BeginThread" needs to be followed by a "CloseThread". The implementation of TThread did not respect this yet.
Note: The only RTL where this could lead to problems is for BeOS with the old threading implementation as this does not use "BeginThread" at all (the newer implementation does).

rtl/objpas/classes/classes.inc, TThread.Destroy:
  * call "CloseThread" if the thread handle is valid (mimics the logic of the Windows RTL)
rtl/win/tthread.inc, TThread.SysDestroy:
  * remove the call to "CloseHandle"; this is done by "CloseThread" afterwards

git-svn-id: trunk@24313 -
2013-04-23 20:13:07 +00:00

125 lines
3.1 KiB
PHP

{ Thread management routines }
procedure TThread.SysCreate(CreateSuspended: Boolean;
const StackSize: SizeUInt);
begin
FSuspended := CreateSuspended;
FInitialSuspended := CreateSuspended;
{ Always start in suspended state, will be resumed in AfterConstruction if necessary
See Mantis #16884 }
FHandle := BeginThread(nil, StackSize, @ThreadProc, pointer(self), CREATE_SUSPENDED,
FThreadID);
if FHandle = TThreadID(0) then
raise EThread.CreateFmt(SThreadCreateError, [SysErrorMessage(getlasterror)]);
FFatalException := nil;
end;
procedure TThread.SysDestroy;
begin
if FHandle<>0 then
begin
{ Don't check Suspended. If the thread has been externally suspended (which is
deprecated and strongly discouraged), it's better to deadlock here than
to silently free the object and leave OS resources leaked. }
if not FFinished {and not Suspended} then
begin
Terminate;
{ Allow the thread function to perform the necessary cleanup. Since
we've just set Terminated flag, it won't call Execute. }
if FInitialSuspended then
Start;
WaitFor;
end;
end;
FFatalException.Free;
FFatalException := nil;
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;
WaitHandles : array[0..1] of THandle;
begin
if GetCurrentThreadID = MainThreadID then
begin
WaitHandles[0]:=FHandle;
WaitHandles[1]:=THandle(SynchronizeTimeoutEvent);
while true do
begin
case MsgWaitForMultipleObjects(2, WaitHandles, False, INFINITE, QS_SENDMESSAGE) of
WAIT_OBJECT_0:
break;
WAIT_OBJECT_0+1:
CheckSynchronize;
WAIT_OBJECT_0+2:
PeekMessage(Msg, 0, 0, 0, PM_NOREMOVE)
end;
end;
end
else
WaitForSingleObject(ulong(FHandle), INFINITE);
GetExitCodeThread(FHandle, DWord(Result));
end;