tthread.inc 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. { Thread management routines }
  2. procedure TThread.SysCreate(CreateSuspended: Boolean;
  3. const StackSize: SizeUInt);
  4. begin
  5. FSuspended := CreateSuspended;
  6. FInitialSuspended := CreateSuspended;
  7. { Always start in suspended state, will be resumed in AfterConstruction if necessary
  8. See Mantis #16884 }
  9. FHandle := BeginThread(nil, StackSize, @ThreadProc, pointer(self), CREATE_SUSPENDED,
  10. FThreadID);
  11. if FHandle = TThreadID(0) then
  12. raise EThread.CreateFmt(SThreadCreateError, [SysErrorMessage(getlasterror)]);
  13. FFatalException := nil;
  14. end;
  15. procedure TThread.SysDestroy;
  16. begin
  17. if FHandle<>0 then
  18. begin
  19. { Don't check Suspended. If the thread has been externally suspended (which is
  20. deprecated and strongly discouraged), it's better to deadlock here than
  21. to silently free the object and leave OS resources leaked. }
  22. if not FFinished {and not Suspended} then
  23. begin
  24. Terminate;
  25. { Allow the thread function to perform the necessary cleanup. Since
  26. we've just set Terminated flag, it won't call Execute. }
  27. if FInitialSuspended then
  28. Start;
  29. WaitFor;
  30. end;
  31. CloseHandle(FHandle);
  32. end;
  33. FFatalException.Free;
  34. FFatalException := nil;
  35. end;
  36. procedure TThread.CallOnTerminate;
  37. begin
  38. FOnTerminate(Self);
  39. end;
  40. procedure TThread.DoTerminate;
  41. begin
  42. if Assigned(FOnTerminate) then
  43. Synchronize(@CallOnTerminate);
  44. end;
  45. const
  46. Priorities: array [TThreadPriority] of Integer =
  47. (THREAD_PRIORITY_IDLE, THREAD_PRIORITY_LOWEST, THREAD_PRIORITY_BELOW_NORMAL,
  48. THREAD_PRIORITY_NORMAL, THREAD_PRIORITY_ABOVE_NORMAL,
  49. THREAD_PRIORITY_HIGHEST, THREAD_PRIORITY_TIME_CRITICAL);
  50. function TThread.GetPriority: TThreadPriority;
  51. var
  52. P: Integer;
  53. I: TThreadPriority;
  54. begin
  55. P := GetThreadPriority(FHandle);
  56. Result := tpNormal;
  57. for I := Low(TThreadPriority) to High(TThreadPriority) do
  58. if Priorities[I] = P then Result := I;
  59. end;
  60. procedure TThread.SetPriority(Value: TThreadPriority);
  61. begin
  62. SetThreadPriority(FHandle, Priorities[Value]);
  63. end;
  64. procedure TThread.SetSuspended(Value: Boolean);
  65. begin
  66. if Value <> FSuspended then
  67. if Value then
  68. Suspend
  69. else
  70. Resume;
  71. end;
  72. procedure TThread.Suspend;
  73. begin
  74. FSuspended := True;
  75. SuspendThread(FHandle);
  76. end;
  77. procedure TThread.Resume;
  78. begin
  79. if ResumeThread(FHandle) = 1 then FSuspended := False;
  80. end;
  81. procedure TThread.Terminate;
  82. begin
  83. FTerminated := True;
  84. end;
  85. function TThread.WaitFor: Integer;
  86. var
  87. Msg: TMsg;
  88. WaitHandles : array[0..1] of THandle;
  89. begin
  90. if GetCurrentThreadID = MainThreadID then
  91. begin
  92. WaitHandles[0]:=FHandle;
  93. WaitHandles[1]:=THandle(SynchronizeTimeoutEvent);
  94. while true do
  95. begin
  96. case MsgWaitForMultipleObjects(2, WaitHandles, False, INFINITE, QS_SENDMESSAGE) of
  97. WAIT_OBJECT_0:
  98. break;
  99. WAIT_OBJECT_0+1:
  100. CheckSynchronize;
  101. WAIT_OBJECT_0+2:
  102. PeekMessage(Msg, 0, 0, 0, PM_NOREMOVE)
  103. end;
  104. end;
  105. end
  106. else
  107. WaitForSingleObject(ulong(FHandle), INFINITE);
  108. GetExitCodeThread(FHandle, DWord(Result));
  109. end;