home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C++ / Applications / Nuntius 1.2 / src / Nuntius / UThreadBuiltIn.cp < prev    next >
Encoding:
Text File  |  1994-03-14  |  5.9 KB  |  246 lines  |  [TEXT/MPS ]

  1. // Copyright © 1993 Peter Speck (speck@dat.ruc.dk).  All rights reserved.
  2. // UThreadBuiltIn.cp
  3.  
  4. #include "UThreadBuiltIn.h"
  5. #include "UFatalError.h"
  6.  
  7. #include <RsrcGlobals.h>
  8.  
  9. #pragma segment MyThread
  10.  
  11. #define qDebugThreadCommands qDebug & 0
  12.  
  13. #define qDebugSchedule qDebug & 0
  14. #define qDebugScheduleVerbose qDebugSchedule & 0
  15.  
  16. #define qDebugStackSize qDebug & 1
  17.  
  18. const long kInitialStackSize = 24 * 1024;
  19.  
  20. long gLastMaxUsedStackSize = 4000;
  21.  
  22. extern "C" MySwapStacks(Handle fromStackH, Handle toStackH);
  23. // Used in asm code: (UThread.a)
  24.  
  25. Handle gFromStackH, gToStackH;
  26. typedef struct
  27. {
  28.     long fAllocSize;
  29.     long fStartAddr;
  30.     long fSize;
  31.     long fSP;
  32.     long fDataOffset;
  33. } *StackSaveHandleDataPtr;
  34.  
  35.  
  36. //==============================================================================
  37.  
  38. TThreadBuiltIn::TThreadBuiltIn()
  39. {
  40. }
  41.  
  42. pascal void TThreadBuiltIn::Initialize()
  43. {
  44.     inherited::Initialize();
  45.     fStackH = nil;
  46. }
  47.  
  48. void TThreadBuiltIn::IThreadBuiltIn(Boolean isMainThread, const char *debugDoingWhat)
  49. {
  50.     inherited::IThread(isMainThread, debugDoingWhat);
  51.     FailInfo fi;
  52.     if (fi.Try())
  53.     {
  54.         fStackH = NewPermHandle(kInitialStackSize);
  55.         // see UThread.a: initial values
  56.         StackSaveHandleDataPtr sshdP = StackSaveHandleDataPtr(*fStackH);
  57.         sshdP->fAllocSize = kInitialStackSize;
  58.         sshdP->fStartAddr = 0;
  59.         sshdP->fSize = 0;
  60.         sshdP->fSP = 0;
  61.         sshdP->fDataOffset = 0;
  62.         fi.Success();
  63.     }
  64.     else // fail
  65.     {
  66.         FreeIfObject(this);
  67.         fi.ReSignal();
  68.     }
  69. }
  70.  
  71. pascal void TThreadBuiltIn::Free()
  72. {
  73.     DisposeIfHandle(fStackH); fStackH = nil;
  74.     inherited::Free();
  75. }
  76.  
  77. void TThreadBuiltIn::Die()
  78. {
  79.     inherited::Die();
  80.     TThreadBuiltIn *thread = (TThreadBuiltIn*)MySchedule();
  81.     thread->OverwriteWithThisThread();
  82.     PanicExitToShell("In TThreadBuiltIn::Die, got past end of world.");
  83. }
  84. //==============================================================================
  85.  
  86. void TThreadBuiltIn::StartThread()
  87. {
  88.     // NO LOCALS ARE ALLOWED as SwapStacks are called
  89.     //
  90.     if (gAllThreads->GetEqualItemNo(this) != kEmptyIndex)
  91.         PanicExitToShell("Trying to StartThread() a running thread");
  92.     MySwapStacks(fStackH, nil);
  93. #if qDebugThreadsCreate
  94.     fprintf(stderr, "StartThread() at $%lx after MySwapStacks(), gAllThreads index = %ld\n", long(this), gAllThreads->GetEqualItemNo(this));
  95. #endif
  96.     if (gAllThreads->GetEqualItemNo(this) != kEmptyIndex)
  97.     {
  98.         // the code below have been executed and then we are the new thread
  99.         RestoreState();
  100.         return;
  101.     }
  102.     gAllThreads->InsertLast(this);
  103.     fIsStarted = true;
  104. }
  105.  
  106. void TThreadBuiltIn::SwapThread()
  107. {
  108.     TThreadBuiltIn *nextThread = (TThreadBuiltIn*)MySchedule();
  109.     if (nextThread == this)
  110.     {
  111. #if qDebug
  112.         fprintf(stderr, "Yeild (MySchedule) to current thread\n");
  113. #endif
  114.         return;
  115.     }
  116.     SaveState();
  117.     MySwapStacks(fStackH, nextThread->fStackH);
  118.     RestoreState();
  119. #if qDebugStackSize
  120.     if (StackSaveHandleDataPtr(*fStackH)->fSize > gLastMaxUsedStackSize)
  121.     {
  122.         fprintf(stderr, "New max stack size: %ld (old = %ld)\n", StackSaveHandleDataPtr(*fStackH)->fSize, gLastMaxUsedStackSize);
  123.         gLastMaxUsedStackSize = StackSaveHandleDataPtr(*fStackH)->fSize;
  124.     }
  125. #endif
  126. }
  127.  
  128. void TThreadBuiltIn::OverwriteWithThisThread()
  129. {
  130.     FailNonObject(this);
  131. #if qDebugThreadsCreate
  132.     fprintf(stderr, "OverwriteWithThisThread for thread at %lx\n", long(this));
  133. #endif
  134.     MySwapStacks(nil, fStackH);
  135. #if qDebug
  136.     FailNonObject(this);
  137. #endif
  138.     RestoreState();
  139.     if (gCurThread != this)
  140.         PanicExitToShell("TThreadBuiltIn::OverwriteWithThisThread: 'this' is not gCurThread");
  141.     fLastYieldTick = TickCount();
  142. #if qDebugScheduleVerbose
  143.     fprintf(stderr, "» Thread at $%lx\n", long(this));
  144. #endif
  145. }
  146.  
  147. void TThreadBuiltIn::DumpDebugDescription()
  148. {
  149.     inherited::DumpDebugDescription();
  150.     fprintf(stderr, "       used-stack = %ld, stack-alloc = %ld\n", StackSaveHandleDataPtr(*fStackH)->fSize, StackSaveHandleDataPtr(*fStackH)->fAllocSize);
  151. }
  152. //===============================================================================
  153. class TExecuteCommandInNewThreadCommand : public TCommand
  154. {
  155.     public:
  156.         pascal void DoIt();
  157.  
  158.         pascal void Initialize();
  159.         void IExecuteCommandInNewThreadCommand(TCommand *command, TThread *thread); // owns the thread
  160.         pascal void Free();
  161.     protected:
  162.         TCommand *fThreadCommand;
  163.         TThread *fThread;
  164. };
  165.  
  166.  
  167. pascal void TExecuteCommandInNewThreadCommand::Initialize()
  168. {
  169.     inherited::Initialize();
  170.     fThreadCommand = nil;
  171.     fThread = nil;
  172. }
  173.  
  174. void TExecuteCommandInNewThreadCommand::IExecuteCommandInNewThreadCommand(TCommand *command, TThread *thread)
  175. {
  176.     inherited::ICommand(cExecuteCommandInNewThreadCommand, nil, false, false, nil);
  177.     fThreadCommand = command;
  178.     fThread = thread;
  179. }
  180.  
  181. pascal void TExecuteCommandInNewThreadCommand::Free()
  182. {
  183.     FreeIfObject(fThreadCommand); fThreadCommand = nil;
  184.     if (fThread)
  185.         fThread->Die();
  186.     fThread = nil;
  187.     inherited::Free();
  188. }
  189.  
  190. pascal void TExecuteCommandInNewThreadCommand::DoIt()
  191. {
  192.     TCommand *cmd = fThreadCommand;
  193.     VOLATILE(cmd);
  194.     fThreadCommand = nil;
  195.  
  196.     TThread *thread = fThread;
  197.     VOLATILE(thread);
  198.     fThread = nil;
  199.  
  200.     ( (TThreadBuiltIn*)thread)->StartThread();
  201.     // 'this' is invalid from now on, as the command object is disposed
  202.     if (gCurThread != thread)
  203.         return;
  204.     ThreadExecuteCommand(cmd);
  205. }
  206.  
  207. TThread *ExecuteInNewThreadBuiltIn(TCommand *command, const char *debugDoingWhat)
  208. {
  209.     TThread *thread = nil;
  210.     VOLATILE(thread);
  211.     TExecuteCommandInNewThreadCommand *cmd = nil;
  212.     VOLATILE(cmd);
  213.     FailInfo fi;
  214.     if (fi.Try())
  215.     {
  216.         TThreadBuiltIn *t = new TThreadBuiltIn();
  217.         t->IThreadBuiltIn(false, debugDoingWhat);
  218.         thread = t;
  219.         FailSpaceIsLow();
  220.         
  221.         TExecuteCommandInNewThreadCommand *c = new TExecuteCommandInNewThreadCommand();
  222.         c->IExecuteCommandInNewThreadCommand(command, thread);
  223.         cmd = c;
  224.         
  225.         FailSpaceIsLow();
  226.         gApplication->PostCommand(cmd);
  227.         fi.Success();
  228.         return thread;
  229.     }
  230.     else // fail
  231.     {
  232.         FreeIfObject(cmd); cmd = nil;
  233.         FreeIfObject(thread); thread = nil;
  234.         FreeIfObject(command); command = nil;
  235.         fi.ReSignal();
  236.     }
  237. }
  238. //===========================================================================
  239. TThread *CreateMainThreadBuiltIn()
  240. {
  241.     TThreadBuiltIn *thread = new TThreadBuiltIn();
  242.     thread->IThreadBuiltIn(true, "main thread");
  243.     thread->StartThread();
  244.     return thread;
  245. }
  246.