|
@@ -80,6 +80,8 @@ var
|
|
|
ThreadQueueTail: TThread.PThreadQueueEntry;
|
|
|
{ used for serialized access to the queue }
|
|
|
ThreadQueueLock: TRtlCriticalSection;
|
|
|
+ { usage counter for ThreadQueueLock }
|
|
|
+ ThreadQueueLockCounter : longint;
|
|
|
{ this list holds all instances of external threads that need to be freed at
|
|
|
the end of the program }
|
|
|
ExternalThreads: TThreadList;
|
|
@@ -224,6 +226,9 @@ constructor TThread.Create(CreateSuspended: Boolean;
|
|
|
const StackSize: SizeUInt);
|
|
|
begin
|
|
|
inherited Create;
|
|
|
+{$ifdef FPC_HAS_FEATURE_THREADING}
|
|
|
+ InterlockedIncrement(ThreadQueueLockCounter);
|
|
|
+{$endif}
|
|
|
if FExternalThread then
|
|
|
{$ifdef FPC_HAS_FEATURE_THREADING}
|
|
|
FThreadID := GetCurrentThreadID
|
|
@@ -246,6 +251,10 @@ begin
|
|
|
end;
|
|
|
RemoveQueuedEvents(Self);
|
|
|
DoneSynchronizeEvent;
|
|
|
+{$ifdef FPC_HAS_FEATURE_THREADING}
|
|
|
+ if InterlockedDecrement(ThreadQueueLockCounter)=0 then
|
|
|
+ DoneCriticalSection(ThreadQueueLock);
|
|
|
+{$endif}
|
|
|
{ set CurrentThreadVar to Nil? }
|
|
|
inherited Destroy;
|
|
|
end;
|
|
@@ -2454,6 +2463,7 @@ procedure CommonInit;
|
|
|
begin
|
|
|
{$ifdef FPC_HAS_FEATURE_THREADING}
|
|
|
SynchronizeTimeoutEvent:=RtlEventCreate;
|
|
|
+ InterlockedIncrement(ThreadQueueLockCounter);
|
|
|
InitCriticalSection(ThreadQueueLock);
|
|
|
MainThreadID:=GetCurrentThreadID;
|
|
|
{$else}
|
|
@@ -2522,17 +2532,25 @@ begin
|
|
|
FreeAndNil(ExternalThreads);
|
|
|
{$ifdef FPC_HAS_FEATURE_THREADING}
|
|
|
RtlEventDestroy(SynchronizeTimeoutEvent);
|
|
|
+ try
|
|
|
+ System.EnterCriticalSection(ThreadQueueLock);
|
|
|
{$endif}
|
|
|
{ clean up the queue, but keep in mind that the entries used for Synchronize
|
|
|
are owned by the corresponding TThread }
|
|
|
- while Assigned(ThreadQueueHead) do begin
|
|
|
- tmpentry := ThreadQueueHead;
|
|
|
- ThreadQueueHead := tmpentry^.Next;
|
|
|
- if not Assigned(tmpentry^.SyncEvent) then
|
|
|
- Dispose(tmpentry);
|
|
|
- end;
|
|
|
+ while Assigned(ThreadQueueHead) do begin
|
|
|
+ tmpentry := ThreadQueueHead;
|
|
|
+ ThreadQueueHead := tmpentry^.Next;
|
|
|
+ if not Assigned(tmpentry^.SyncEvent) then
|
|
|
+ Dispose(tmpentry);
|
|
|
+ end;
|
|
|
+ { We also need to reset ThreadQueueTail }
|
|
|
+ ThreadQueueTail := nil;
|
|
|
{$ifdef FPC_HAS_FEATURE_THREADING}
|
|
|
- DoneCriticalSection(ThreadQueueLock);
|
|
|
+ finally
|
|
|
+ System.LeaveCriticalSection(ThreadQueueLock);
|
|
|
+ end;
|
|
|
+ if InterlockedDecrement(ThreadQueueLockCounter)=0 then
|
|
|
+ DoneCriticalSection(ThreadQueueLock);
|
|
|
{$endif}
|
|
|
end;
|
|
|
|