| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543 | {    This file is part of the Free Pascal Run time library.    Copyright (c) 2000 by the Free Pascal development team    OS independent thread functions/overloads    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. **********************************************************************}Var  CurrentTM : TThreadManager;{*****************************************************************************                           Threadvar initialization*****************************************************************************}    procedure InitThread(stklen:SizeUInt);      begin        SysResetFPU;        SysInitFPU;{$ifndef HAS_MEMORYMANAGER}        { initialize this thread's heap }        InitHeapThread;{$endif HAS_MEMORYMANAGER}        if MemoryManager.InitThread <> nil then          MemoryManager.InitThread();{$ifdef FPC_HAS_FEATURE_WIDESTRINGS}        if assigned(widestringmanager.ThreadInitProc) then          widestringmanager.ThreadInitProc;{$endif FPC_HAS_FEATURE_WIDESTRINGS}        { ExceptAddrStack and ExceptObjectStack are threadvars       }        { so every thread has its on exception handling capabilities }        SysInitExceptions;        { Open all stdio fds again }        SysInitStdio;        InOutRes:=0;        // ErrNo:=0;        { Stack checking }        StackLength:= CheckInitialStkLen(stkLen);        StackBottom:=Sptr - StackLength;        ThreadID := CurrentTM.GetCurrentThreadID();      end;    procedure DoneThread;      begin{$ifdef FPC_HAS_FEATURE_WIDESTRINGS}        if assigned(widestringmanager.ThreadFiniProc) then          widestringmanager.ThreadFiniProc;{$endif FPC_HAS_FEATURE_WIDESTRINGS}{$ifndef HAS_MEMORYMANAGER}        FinalizeHeap;{$endif HAS_MEMORYMANAGER}        if MemoryManager.DoneThread <> nil then          MemoryManager.DoneThread();        CurrentTM.ReleaseThreadVars;      end;{*****************************************************************************                            Overloaded functions*****************************************************************************}    function BeginThread(ThreadFunction : tthreadfunc) : TThreadID;      var        dummy : TThreadID;      begin        BeginThread:=BeginThread(nil,DefaultStackSize,ThreadFunction,nil,0,dummy);      end;    function BeginThread(ThreadFunction : tthreadfunc;p : pointer) : TThreadID;      var        dummy : TThreadID;      begin        BeginThread:=BeginThread(nil,DefaultStackSize,ThreadFunction,p,0,dummy);      end;    function BeginThread(ThreadFunction : tthreadfunc;p : pointer;var ThreadId : TThreadID) : TThreadID;      begin        BeginThread:=BeginThread(nil,DefaultStackSize,ThreadFunction,p,0,ThreadId);      end;    function BeginThread(ThreadFunction : tthreadfunc;p : pointer;                     var ThreadId : TThreadID; const stacksize: SizeUInt) : TThreadID;      begin        BeginThread:=BeginThread(nil,stacksize,ThreadFunction,p,0,ThreadId);      end;    procedure EndThread;      begin        EndThread(0);      end;function BeginThread(sa : Pointer;stacksize : SizeUInt; ThreadFunction : tthreadfunc;p : pointer;creationFlags : dword;  var ThreadId : TThreadID) : TThreadID;begin  Result:=CurrentTM.BeginThread(sa,stacksize,threadfunction,P,creationflags,ThreadID);end;procedure FlushThread;begin{$ifdef FPC_HAS_FEATURE_CONSOLEIO}  { Make sure that all output is written to the redirected file }  Flush(Output);  Flush(ErrOutput);  Flush(StdOut);  Flush(StdErr);{$endif FPC_HAS_FEATURE_CONSOLEIO}end;procedure EndThread(ExitCode : DWord);begin  FlushThread;  CurrentTM.EndThread(ExitCode);end;function  SuspendThread (threadHandle : TThreadID) : dword;begin  Result:=CurrentTM.SuspendThread(ThreadHandle);end;function ResumeThread  (threadHandle : TThreadID) : dword;begin  Result:=CurrentTM.ResumeThread(ThreadHandle);end;procedure ThreadSwitch;begin  CurrentTM.ThreadSwitch;end;function  KillThread (threadHandle : TThreadID) : dword;begin  Result:=CurrentTM.KillThread(ThreadHandle);end;function  WaitForThreadTerminate (threadHandle : TThreadID; TimeoutMs : longint) : dword;begin  Result:=CurrentTM.WaitForThreadTerminate(ThreadHandle,TimeOutMS);end;function  ThreadSetPriority (threadHandle : TThreadID; Prio: longint): boolean;begin  Result:=CurrentTM.ThreadSetPriority(ThreadHandle,Prio);end;function  ThreadGetPriority (threadHandle : TThreadID): longint;begin  Result:=CurrentTM.ThreadGetPriority(ThreadHandle);end;function  GetCurrentThreadId : TThreadID;begin  Result:=CurrentTM.GetCurrentThreadID();end;procedure InitCriticalSection(var cs : TRTLCriticalSection);begin  CurrentTM.InitCriticalSection(cs);end;procedure DoneCriticalsection(var cs : TRTLCriticalSection);begin  CurrentTM.DoneCriticalSection(cs);end;procedure EnterCriticalsection(var cs : TRTLCriticalSection);begin  CurrentTM.EnterCriticalSection(cs);end;procedure LeaveCriticalsection(var cs : TRTLCriticalSection);begin  CurrentTM.LeaveCriticalSection(cs);end;Function GetThreadManager(Var TM : TThreadManager) : Boolean;begin  TM:=CurrentTM;  Result:=True;end;Function SetThreadManager(Const NewTM : TThreadManager; Var OldTM : TThreadManager) : Boolean;begin  GetThreadManager(OldTM);  Result:=SetThreadManager(NewTM);end;Function SetThreadManager(Const NewTM : TThreadManager) : Boolean;begin  Result:=True;  If Assigned(CurrentTM.DoneManager) then    Result:=CurrentTM.DoneManager();  If Result then    begin    CurrentTM:=NewTM;    If Assigned(CurrentTM.InitManager) then      Result:=CurrentTM.InitManager();    end;end;function  BasicEventCreate(EventAttributes : Pointer; AManualReset,InitialState : Boolean;const Name : ansistring):pEventState;begin  result:=currenttm.BasicEventCreate(EventAttributes,AManualReset,InitialState, Name);end;procedure basiceventdestroy(state:peventstate);begin  currenttm.basiceventdestroy(state);end;procedure basiceventResetEvent(state:peventstate);begin  currenttm.basiceventResetEvent(state);end;procedure basiceventSetEvent(state:peventstate);begin  currenttm.basiceventSetEvent(state);end;function  basiceventWaitFor(Timeout : Cardinal;state:peventstate) : longint;begin result:=currenttm.basiceventWaitFor(Timeout,state);end;function  RTLEventCreate :PRTLEvent;begin  result:=currenttm.rtleventcreate();end;procedure RTLeventdestroy(state:pRTLEvent);begin  currenttm.rtleventdestroy(state);end;procedure RTLeventSetEvent(state:pRTLEvent);begin  currenttm.rtleventsetEvent(state);end;procedure RTLeventResetEvent(state:pRTLEvent);begin  currenttm.rtleventResetEvent(state);end;procedure RTLeventWaitFor(state:pRTLEvent);begin  currenttm.rtleventWaitFor(state);end;procedure RTLeventWaitFor(state:pRTLEvent;timeout : longint);begin  currenttm.rtleventWaitForTimeout(state,timeout);end;procedure RTLeventsync(m:trtlmethod;p:tprocedure);begin  currenttm.rtleventsync(m,p);end;{ ---------------------------------------------------------------------    ThreadManager which gives run-time error. Use if no thread support.  ---------------------------------------------------------------------}{$ifndef DISABLE_NO_THREAD_MANAGER}{ resourcestrings are not supported by the system unit,  they are in the objpas unit and not available for fpc/tp modes }const  SNoThreads = 'This binary has no thread support compiled in.';  SRecompileWithThreads = 'Recompile the application with a thread-driver in the program uses clause before other units using thread.';Procedure NoThreadError;begin{$ifdef FPC_HAS_FEATURE_CONSOLEIO}  If IsConsole then    begin    Writeln(StdErr,SNoThreads);    Writeln(StdErr,SRecompileWithThreads);    end;{$endif FPC_HAS_FEATURE_CONSOLEIO}  RunError(232)end;function NoBeginThread(sa : Pointer;stacksize : PtrUInt;                     ThreadFunction : tthreadfunc;p : pointer;                     creationFlags : dword; var ThreadId : TThreadID) : TThreadID;begin  NoThreadError;end;procedure NoEndThread(ExitCode : DWord);begin  NoThreadError;end;function  NoThreadHandler (threadHandle : TThreadID) : dword;begin  NoThreadError;end;procedure NoThreadSwitch;  {give time to other threads}begin  NoThreadError;end;function  NoWaitForThreadTerminate (threadHandle : TThreadID; TimeoutMs : longint) : dword;  {0=no timeout}begin  NoThreadError;end;function  NoThreadSetPriority (threadHandle : TThreadID; Prio: longint): boolean; {-15..+15, 0=normal}begin  NoThreadError;end;function  NoThreadGetPriority (threadHandle : TThreadID): longint;begin  NoThreadError;end;function  NoGetCurrentThreadId : TThreadID;begin  if IsMultiThread then    NoThreadError  else    ThreadingAlreadyUsed:=true;  result:=ThreadID;end;procedure NoCriticalSection(var CS);begin  if IsMultiThread then    NoThreadError  else    ThreadingAlreadyUsed:=true;end;procedure NoInitThreadvar(var offset : dword;size : dword);begin  NoThreadError;end;function NoRelocateThreadvar(offset : dword) : pointer;begin  NoThreadError;end;procedure NoAllocateThreadVars;begin  NoThreadError;end;procedure NoReleaseThreadVars;begin  NoThreadError;end;function  noBasicEventCreate(EventAttributes : Pointer; AManualReset,InitialState : Boolean;const Name : ansistring):pEventState;begin  NoThreadError;end;procedure nobasiceventdestroy(state:peventstate);begin  NoThreadError;end;procedure nobasiceventResetEvent(state:peventstate);begin  NoThreadError;end;procedure nobasiceventSetEvent(state:peventstate);begin  NoThreadError;end;function  nobasiceventWaitFor(Timeout : Cardinal;state:peventstate) : longint;begin  NoThreadError;end;function  NORTLEventCreate :PRTLEvent;begin  if IsMultiThread then    NoThreadError  else    ThreadingAlreadyUsed:=trueend;procedure NORTLeventdestroy(state:pRTLEvent);begin  if IsMultiThread then    NoThreadError  else    ThreadingAlreadyUsed:=trueend;procedure NORTLeventSetEvent(state:pRTLEvent);begin  NoThreadError;end;procedure NORTLeventWaitFor(state:pRTLEvent);  begin    NoThreadError;  end;procedure NORTLeventWaitForTimeout(state:pRTLEvent;timeout : longint);  begin    NoThreadError;  end;procedure NORTLeventsync(m:trtlmethod;p:tprocedure);  begin    NoThreadError;  end;function NoSemaphoreInit: Pointer;begin  NoThreadError;end;procedure NoSemaphoreWait(const FSem: Pointer);begin  NoThreadError;end;procedure NoSemaphorePost(const FSem: Pointer);begin  NoThreadError;end;procedure NoSemaphoreDestroy(const FSem: Pointer);begin  NoThreadError;end;Var  NoThreadManager : TThreadManager;Procedure SetNoThreadManager;begin  With NoThreadManager do    begin    InitManager            :=Nil;    DoneManager            :=Nil;    BeginThread            :=@NoBeginThread;    EndThread              :=@NoEndThread;    SuspendThread          :=@NoThreadHandler;    ResumeThread           :=@NoThreadHandler;    KillThread             :=@NoThreadHandler;    ThreadSwitch           :=@NoThreadSwitch;    WaitForThreadTerminate :=@NoWaitForThreadTerminate;    ThreadSetPriority      :=@NoThreadSetPriority;    ThreadGetPriority      :=@NoThreadGetPriority;    GetCurrentThreadId     :=@NoGetCurrentThreadId;    InitCriticalSection    :=@NoCriticalSection;    DoneCriticalSection    :=@NoCriticalSection;    EnterCriticalSection   :=@NoCriticalSection;    LeaveCriticalSection   :=@NoCriticalSection;    InitThreadVar          :=@NoInitThreadVar;    RelocateThreadVar      :=@NoRelocateThreadVar;    AllocateThreadVars     :=@NoAllocateThreadVars;    ReleaseThreadVars      :=@NoReleaseThreadVars;    BasicEventCreate       :=@NoBasicEventCreate;    basiceventdestroy      :=@Nobasiceventdestroy;    basiceventResetEvent   :=@NobasiceventResetEvent;    basiceventSetEvent     :=@NobasiceventSetEvent;    basiceventWaitFor      :=@NobasiceventWaitFor;    rtlEventCreate         :=@NortlEventCreate;    rtleventdestroy        :=@Nortleventdestroy;    rtleventSetEvent       :=@NortleventSetEvent;    rtleventWaitFor        :=@NortleventWaitFor;    rtleventsync           :=@Nortleventsync;    rtleventwaitfortimeout :=@NortleventWaitForTimeout;    // semaphores stuff    SemaphoreInit          :=@NoSemaphoreInit;    SemaphoreDestroy       :=@NoSemaphoreDestroy;    SemaphoreWait          :=@NoSemaphoreWait;    SemaphorePost          :=@NoSemaphorePost;    end;  SetThreadManager(NoThreadManager);end;{$endif DISABLE_NO_THREAD_MANAGER}
 |