mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-07 05:08:06 +02:00

Notes: - Netware had a ThreadSwitch in there, but that is not really required - some platform were missing the setting of FTerminated to True, thus they'll now do that as well git-svn-id: trunk@46543 -
226 lines
4.7 KiB
PHP
226 lines
4.7 KiB
PHP
{
|
|
This file is part of the Free Component Library (FCL)
|
|
Copyright (c) 2003-2004 Armin Diehl, member of the Free Pascal
|
|
development team
|
|
|
|
Netware clib TThread implementation
|
|
|
|
See the file COPYING.FPC, included in this distribution,
|
|
for details about the copyright.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
**********************************************************************}
|
|
|
|
|
|
type
|
|
PThreadRec=^TThreadRec;
|
|
TThreadRec=record
|
|
thread : TThread;
|
|
next : PThreadRec;
|
|
end;
|
|
|
|
var
|
|
ThreadRoot : PThreadRec;
|
|
ThreadsInited : boolean;
|
|
DisableRemoveThread : boolean;
|
|
|
|
Const
|
|
ThreadCount: longint = 0;
|
|
|
|
{function ThreadSelf:TThread;
|
|
var
|
|
hp : PThreadRec;
|
|
sp : longint;
|
|
begin
|
|
sp:=SPtr;
|
|
hp:=ThreadRoot;
|
|
while assigned(hp) do
|
|
begin
|
|
if (sp<=hp^.Thread.FStackPointer) and
|
|
(sp>(hp^.Thread.FStackPointer-hp^.Thread.FStackSize)) then
|
|
begin
|
|
Result:=hp^.Thread;
|
|
exit;
|
|
end;
|
|
hp:=hp^.next;
|
|
end;
|
|
Result:=nil;
|
|
end;}
|
|
|
|
|
|
procedure InitThreads;
|
|
begin
|
|
ThreadRoot:=nil;
|
|
ThreadsInited:=true;
|
|
DisableRemoveThread:=false;
|
|
end;
|
|
|
|
{DoneThreads will terminate all remaining threads}
|
|
procedure DoneThreads;
|
|
var
|
|
hp,next : PThreadRec;
|
|
begin
|
|
DisableRemoveThread := true; {to avoid that Destroy calling RemoveThread modifies Thread List}
|
|
while assigned(ThreadRoot) do
|
|
begin
|
|
ThreadRoot^.Thread.Destroy;
|
|
hp:=ThreadRoot;
|
|
ThreadRoot:=ThreadRoot^.Next;
|
|
dispose(hp);
|
|
{$ifdef DEBUG_MT}
|
|
ConsolePrintf(#13'DoneThreads: called destroy, remaining threads: %d ThreadRoot: %x'#13#10,ThreadCount,longint(ThreadRoot));
|
|
{$endif}
|
|
end;
|
|
ThreadsInited:=false;
|
|
end;
|
|
|
|
|
|
procedure AddThread(t:TThread);
|
|
var
|
|
hp : PThreadRec;
|
|
begin
|
|
{ Need to initialize threads ? }
|
|
if not ThreadsInited then
|
|
InitThreads;
|
|
|
|
{ Put thread in the linked list }
|
|
new(hp);
|
|
hp^.Thread:=t;
|
|
hp^.next:=ThreadRoot;
|
|
ThreadRoot:=hp;
|
|
|
|
inc(ThreadCount);
|
|
end;
|
|
|
|
|
|
procedure RemoveThread(t:TThread);
|
|
var
|
|
lasthp,hp : PThreadRec;
|
|
begin
|
|
if not DisableRemoveThread then {disabled while in DoneThreads}
|
|
begin
|
|
hp:=ThreadRoot;
|
|
lasthp:=nil;
|
|
while assigned(hp) do
|
|
begin
|
|
if hp^.Thread=t then
|
|
begin
|
|
if assigned(lasthp) then
|
|
lasthp^.next:=hp^.next
|
|
else
|
|
ThreadRoot:=hp^.next;
|
|
dispose(hp);
|
|
Dec(ThreadCount);
|
|
if ThreadCount = 0 then ThreadsInited := false;
|
|
exit;
|
|
end;
|
|
lasthp:=hp;
|
|
hp:=hp^.next;
|
|
end;
|
|
end else
|
|
dec(ThreadCount);
|
|
end;
|
|
|
|
|
|
procedure TThread.SysCreate(CreateSuspended: Boolean;
|
|
const StackSize: SizeUInt);
|
|
var
|
|
Flags: Integer;
|
|
begin
|
|
AddThread(self);
|
|
FSuspended := CreateSuspended;
|
|
{ Create new thread }
|
|
FHandle := BeginThread (@ThreadProc,pointer(self));
|
|
if FSuspended then Suspend;
|
|
FThreadID := FHandle;
|
|
FFatalException := nil;
|
|
end;
|
|
|
|
|
|
procedure TThread.SysDestroy;
|
|
begin
|
|
if not FFinished then
|
|
begin
|
|
Terminate;
|
|
if Suspended then
|
|
ResumeThread (FHandle); {netware can not kill a thread, the thread has to}
|
|
{leave it's execute routine if terminated is true}
|
|
WaitFor; {wait for the thread to terminate}
|
|
end;
|
|
FFatalException.Free;
|
|
FFatalException := nil;
|
|
RemoveThread(self); {remove it from the list of active threads}
|
|
end;
|
|
|
|
|
|
procedure TThread.CallOnTerminate;
|
|
begin
|
|
FOnTerminate(Self);
|
|
end;
|
|
|
|
procedure TThread.DoTerminate;
|
|
begin
|
|
if Assigned(FOnTerminate) then
|
|
Synchronize(@CallOnTerminate);
|
|
end;
|
|
|
|
|
|
const
|
|
Priorities: array [TThreadPriority] of Integer =
|
|
(THREAD_PRIORITY_IDLE, THREAD_PRIORITY_LOWEST, THREAD_PRIORITY_BELOW_NORMAL,
|
|
THREAD_PRIORITY_NORMAL, THREAD_PRIORITY_ABOVE_NORMAL,
|
|
THREAD_PRIORITY_HIGHEST, THREAD_PRIORITY_TIME_CRITICAL);
|
|
|
|
function TThread.GetPriority: TThreadPriority;
|
|
var
|
|
P: Integer;
|
|
I: TThreadPriority;
|
|
begin
|
|
P := ThreadGetPriority(FHandle);
|
|
Result := tpNormal;
|
|
for I := Low(TThreadPriority) to High(TThreadPriority) do
|
|
if Priorities[I] = P then Result := I;
|
|
end;
|
|
|
|
|
|
procedure TThread.SetPriority(Value: TThreadPriority);
|
|
begin
|
|
ThreadSetPriority(FHandle, Priorities[Value]);
|
|
end;
|
|
|
|
|
|
procedure TThread.SetSuspended(Value: Boolean);
|
|
begin
|
|
if Value <> FSuspended then
|
|
if Value then
|
|
Suspend
|
|
else
|
|
Resume;
|
|
end;
|
|
|
|
|
|
procedure TThread.Suspend;
|
|
begin
|
|
SuspendThread (FHandle);
|
|
FSuspended := true;
|
|
end;
|
|
|
|
|
|
procedure TThread.Resume;
|
|
begin
|
|
ResumeThread (FHandle);
|
|
FSuspended := False;
|
|
end;
|
|
|
|
|
|
function TThread.WaitFor: Integer;
|
|
begin
|
|
Result := WaitForThreadTerminate (FHandle,0);
|
|
if Result = 0 then
|
|
FHandle := 0;
|
|
end;
|
|
|