tthread.inc 3.4 KB

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