|
@@ -1,17 +1,17 @@
|
|
|
{
|
|
|
- This file is part of the Free Component Library (FCL)
|
|
|
- Copyright (c) 1999-2000 by Peter Vreman
|
|
|
+ This file is part of the Free Pascal run time library.
|
|
|
+ (c) 2000-2003 by Marco van de Voort
|
|
|
+ member of the Free Pascal development team.
|
|
|
|
|
|
- Darwin TThread implementation
|
|
|
+ See the file COPYING.FPC, included in this distribution,
|
|
|
+ for details about the copyright.
|
|
|
|
|
|
- See the file COPYING.FPC, included in this distribution,
|
|
|
- for details about the copyright.
|
|
|
+ TThread implementation old (1.0) and new (pthreads) style
|
|
|
|
|
|
- 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.
|
|
|
-
|
|
|
- **********************************************************************}
|
|
|
+ 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.
|
|
|
+}
|
|
|
|
|
|
|
|
|
{
|
|
@@ -63,64 +63,10 @@
|
|
|
{$define WRITE_DEBUG := //} // just comment out those lines
|
|
|
{$ENDIF}
|
|
|
|
|
|
-// ========== semaphore stuff ==========
|
|
|
-{
|
|
|
- I don't like this. It eats up 2 filedescriptors for each thread,
|
|
|
- and those are a limited resource. If you have a server programm
|
|
|
- handling client connections (one per thread) it will not be able
|
|
|
- to handle many if we use 2 fds already for internal structures.
|
|
|
- However, right now I don't see a better option unless some sem_*
|
|
|
- functions are added to systhrds.
|
|
|
- I encapsulated all used functions here to make it easier to
|
|
|
- change them completely.
|
|
|
-}
|
|
|
-
|
|
|
-function SemaphoreInit: Pointer;
|
|
|
-begin
|
|
|
- SemaphoreInit := GetMem(SizeOf(TFilDes));
|
|
|
- fppipe(PFilDes(SemaphoreInit)^);
|
|
|
- WRITE_DEBUG('Opened file descriptor ',PFilDes(SemaphoreInit)^[0]);
|
|
|
-end;
|
|
|
-
|
|
|
-procedure SemaphoreWait(const FSem: Pointer);
|
|
|
-var
|
|
|
- b: byte;
|
|
|
-begin
|
|
|
- WRITE_DEBUG('Waiting for file descriptor ',PFilDes(FSem)^[0]);
|
|
|
- repeat
|
|
|
- if fpread(PFilDes(FSem)^[0], b, 1) = -1 then
|
|
|
- WRITE_DEBUG('Error reading from semaphore ',PFilDes(FSem)^[0],' error = ',fpgeterrno);
|
|
|
- until fpgeterrno <> ESysEIntr;
|
|
|
-end;
|
|
|
-
|
|
|
-procedure SemaphorePost(const FSem: Pointer);
|
|
|
-{$ifdef VER2_0}
|
|
|
-var
|
|
|
- b : byte;
|
|
|
-{$endif}
|
|
|
-begin
|
|
|
- WRITE_DEBUG('Activating file descriptor ',PFilDes(FSem)^[0]);
|
|
|
-{$ifdef VER2_0}
|
|
|
- b:=0;
|
|
|
- fpwrite(PFilDes(FSem)^[1], b, 1);
|
|
|
-{$else}
|
|
|
- if fpwrite(PFilDes(FSem)^[1], #0, 1) = -1 then
|
|
|
- WRITE_DEBUG('Error writing file descriptor ',PFilDes(FSem)^[0],' error = ',fpgeterrno);
|
|
|
-{$endif}
|
|
|
-end;
|
|
|
-
|
|
|
-procedure SemaphoreDestroy(const FSem: Pointer);
|
|
|
-begin
|
|
|
- WRITE_DEBUG('Closing file descriptor ',PFilDes(FSem)^[0]);
|
|
|
- fpclose(PFilDes(FSem)^[0]);
|
|
|
- fpclose(PFilDes(FSem)^[1]);
|
|
|
- FreeMemory(FSem);
|
|
|
-end;
|
|
|
-
|
|
|
-// =========== semaphore end ===========
|
|
|
-
|
|
|
var
|
|
|
ThreadsInited: boolean = false;
|
|
|
+ CurrentTM: TThreadManager;
|
|
|
+
|
|
|
const
|
|
|
// stupid, considering its not even implemented...
|
|
|
Priorities: array [TThreadPriority] of Integer =
|
|
@@ -128,9 +74,9 @@ const
|
|
|
|
|
|
procedure InitThreads;
|
|
|
begin
|
|
|
- if not ThreadsInited then begin
|
|
|
+ GetThreadManager(CurrentTM);
|
|
|
+ if not ThreadsInited then
|
|
|
ThreadsInited := true;
|
|
|
- end;
|
|
|
end;
|
|
|
|
|
|
procedure DoneThreads;
|
|
@@ -141,13 +87,14 @@ end;
|
|
|
function ThreadFunc(parameter: Pointer): LongInt;
|
|
|
var
|
|
|
LThread: TThread;
|
|
|
+ c: char;
|
|
|
begin
|
|
|
WRITE_DEBUG('ThreadFunc is here...');
|
|
|
LThread := TThread(parameter);
|
|
|
WRITE_DEBUG('thread initing, parameter = ', LongInt(LThread));
|
|
|
try
|
|
|
if LThread.FInitialSuspended then begin
|
|
|
- SemaphoreWait(LThread.FSem);
|
|
|
+ CurrentTM.SemaphoreWait(LThread.FSem);
|
|
|
if not LThread.FSuspended then begin
|
|
|
LThread.FInitialSuspended := false;
|
|
|
WRITE_DEBUG('going into LThread.Execute');
|
|
@@ -188,13 +135,13 @@ begin
|
|
|
// via BeginThread and creates the first TThread Object in there!
|
|
|
InitThreads;
|
|
|
inherited Create;
|
|
|
- FSem := SemaphoreInit;
|
|
|
+ FSem := CurrentTM.SemaphoreInit;
|
|
|
FSuspended := CreateSuspended;
|
|
|
FSuspendedExternal := false;
|
|
|
FInitialSuspended := CreateSuspended;
|
|
|
FFatalException := nil;
|
|
|
- WRITE_DEBUG('creating thread, self = ',longint(self));
|
|
|
- FHandle:= BeginThread(@ThreadFunc, Pointer(Self), FThreadID, StackSize);
|
|
|
+ WRITE_DEBUG('creating thread, self = ',PtrInt(self));
|
|
|
+ FHandle:= BeginThread(@ThreadFunc, Pointer(Self), FThreadID,StackSize);
|
|
|
WRITE_DEBUG('TThread.Create done');
|
|
|
end;
|
|
|
|
|
@@ -213,12 +160,12 @@ begin
|
|
|
end;
|
|
|
if (FInitialSuspended) then begin
|
|
|
// thread was created suspended but never woken up.
|
|
|
- SemaphorePost(FSem);
|
|
|
+ CurrentTM.SemaphorePost(FSem);
|
|
|
WaitFor;
|
|
|
end;
|
|
|
FFatalException.Free;
|
|
|
FFatalException := nil;
|
|
|
- SemaphoreDestroy(FSem);
|
|
|
+ CurrentTM.SemaphoreDestroy(FSem);
|
|
|
inherited Destroy;
|
|
|
end;
|
|
|
|
|
@@ -236,7 +183,7 @@ begin
|
|
|
if not FSuspended then begin
|
|
|
if FThreadID = GetCurrentThreadID then begin
|
|
|
FSuspended := true;
|
|
|
- SemaphoreWait(FSem);
|
|
|
+ CurrentTM.SemaphoreWait(FSem);
|
|
|
end else begin
|
|
|
FSuspendedExternal := true;
|
|
|
SuspendThread(FHandle);
|
|
@@ -250,7 +197,7 @@ begin
|
|
|
if (not FSuspendedExternal) then begin
|
|
|
if FSuspended then begin
|
|
|
FSuspended := False;
|
|
|
- SemaphorePost(FSem);
|
|
|
+ CurrentTM.SemaphorePost(FSem);
|
|
|
end;
|
|
|
end else begin
|
|
|
FSuspendedExternal := false;
|
|
@@ -266,7 +213,7 @@ end;
|
|
|
|
|
|
function TThread.WaitFor: Integer;
|
|
|
begin
|
|
|
- WRITE_DEBUG('waiting for thread ',ptrint(FHandle));
|
|
|
+ WRITE_DEBUG('waiting for thread ',FHandle);
|
|
|
WaitFor := WaitForThreadTerminate(FHandle, 0);
|
|
|
WRITE_DEBUG('thread terminated');
|
|
|
end;
|