tthread.inc 3.2 KB

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