tthread.inc 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  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 OR STACK_SIZE_PARAM_IS_A_RESERVATION,
  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. end;
  32. FFatalException.Free;
  33. FFatalException := nil;
  34. end;
  35. procedure TThread.CallOnTerminate;
  36. begin
  37. FOnTerminate(Self);
  38. end;
  39. procedure TThread.DoTerminate;
  40. begin
  41. if Assigned(FOnTerminate) then
  42. Synchronize(@CallOnTerminate);
  43. end;
  44. const
  45. Priorities: array [TThreadPriority] of Integer =
  46. (THREAD_PRIORITY_IDLE, THREAD_PRIORITY_LOWEST, THREAD_PRIORITY_BELOW_NORMAL,
  47. THREAD_PRIORITY_NORMAL, THREAD_PRIORITY_ABOVE_NORMAL,
  48. THREAD_PRIORITY_HIGHEST, THREAD_PRIORITY_TIME_CRITICAL);
  49. function TThread.GetPriority: TThreadPriority;
  50. var
  51. P: Integer;
  52. I: TThreadPriority;
  53. begin
  54. P := GetThreadPriority(FHandle);
  55. Result := tpNormal;
  56. for I := Low(TThreadPriority) to High(TThreadPriority) do
  57. if Priorities[I] = P then Result := I;
  58. end;
  59. procedure TThread.SetPriority(Value: TThreadPriority);
  60. begin
  61. SetThreadPriority(FHandle, Priorities[Value]);
  62. end;
  63. procedure TThread.SetSuspended(Value: Boolean);
  64. begin
  65. if Value <> FSuspended then
  66. if Value then
  67. Suspend
  68. else
  69. Resume;
  70. end;
  71. procedure TThread.Suspend;
  72. begin
  73. FSuspended := True;
  74. SuspendThread(FHandle);
  75. end;
  76. procedure TThread.Resume;
  77. begin
  78. if ResumeThread(FHandle) = 1 then FSuspended := False;
  79. end;
  80. procedure TThread.Terminate;
  81. begin
  82. FTerminated := True;
  83. end;
  84. function TThread.WaitFor: Integer;
  85. var
  86. Msg: TMsg;
  87. WaitHandles : array[0..1] of THandle;
  88. begin
  89. if GetCurrentThreadID = MainThreadID then
  90. begin
  91. WaitHandles[0]:=FHandle;
  92. WaitHandles[1]:=THandle(SynchronizeTimeoutEvent);
  93. while true do
  94. begin
  95. case MsgWaitForMultipleObjects(2, WaitHandles, False, INFINITE, QS_SENDMESSAGE) of
  96. WAIT_OBJECT_0:
  97. break;
  98. WAIT_OBJECT_0+1:
  99. CheckSynchronize;
  100. WAIT_OBJECT_0+2:
  101. PeekMessage(Msg, 0, 0, 0, PM_NOREMOVE)
  102. end;
  103. end;
  104. end
  105. else
  106. WaitForSingleObject(ulong(FHandle), INFINITE);
  107. GetExitCodeThread(FHandle, DWord(Result));
  108. end;