home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1998 / MacHack 1998.toast / Papers / C++ Exceptions / µShell / Threads Support / ThreadManager.cp < prev    next >
Encoding:
Text File  |  1998-06-02  |  4.9 KB  |  249 lines  |  [TEXT/CWIE]

  1. #ifndef __THREADMANAGER__
  2. #include "ThreadManager.h"
  3. #endif
  4.  
  5. #include "Toolbox.h"
  6. #include "Exceptions.h"
  7.  
  8. class TThread;
  9.  
  10. struct ThreadTableEntry
  11. {
  12.     ThreadID    id;
  13.     TThread*    obj;
  14. };
  15.  
  16. typedef struct ThreadTable
  17. {
  18.     long                size;
  19.     ThreadTableEntry    data[1];
  20. } ThreadTable, *ThreadTablePtr, **ThreadTableHdl;
  21.  
  22. #define sizeofThreadTable(n)    (sizeof(ThreadTable) - sizeof(ThreadTableEntry) + ((n) * sizeof(ThreadTableEntry)))
  23. #define kThreadTableChunk        4
  24.  
  25. //--------------------------------------------------------------------------------
  26.  
  27. ThreadManager*    ThreadManager::gThreadManager    = nil;
  28. long            ThreadManager::gThreadGestalt    = 0;
  29. long            ThreadManager::gThreadCount        = 0;
  30. ThreadTaskRef    ThreadManager::gTaskRef            = nil;
  31.  
  32. static ThreadTableHdl    gThreadTable        = nil;
  33. static ThreadID            gThreadHintID        = kNoThreadID;
  34. static long                gThreadHintIndex    = 0;
  35.  
  36. //--------------------------------------------------------------------------------
  37.  
  38. #if qDebug
  39. ThreadManager& ThreadManager::GetThreadManager()
  40. {
  41.     if (!gThreadManager)
  42.     {
  43.         Debugger();
  44.     }
  45.  
  46.     return *gThreadManager;
  47. }
  48. #endif
  49.  
  50. //--------------------------------------------------------------------------------
  51.  
  52. ThreadManager::ThreadManager()
  53. {
  54.     WarnIf(gThreadManager != nil, "Instantiating a second ThreadManager");
  55.  
  56.     gThreadManager = this;
  57. }
  58.  
  59. //--------------------------------------------------------------------------------
  60.  
  61. ThreadManager::~ThreadManager()
  62. {
  63.     gThreadManager = nil;
  64. }
  65.  
  66. //--------------------------------------------------------------------------------
  67.  
  68. bool ThreadManager::Validate()
  69. {
  70.     if (Inherited::Validate())
  71.     {
  72.         OSErr err = Gestalt(gestaltThreadMgrAttr, &gThreadGestalt);
  73.     
  74.         if (err == noErr)
  75.         {
  76.             if (HasCFMSymbol(NewThread))
  77.             {
  78.                 return true;
  79.             }
  80.         }
  81.         
  82.         gThreadGestalt = 0;
  83.     }
  84.     
  85.     return false;
  86. }
  87.  
  88. //--------------------------------------------------------------------------------
  89.  
  90. void ThreadManager::Initialize(void)
  91. {
  92.     if (gThreadCount == 0)
  93.     {
  94.         InitializeAfter(Toolbox::GetToolbox());
  95.  
  96.         Inherited::Initialize();
  97.  
  98.         FailOSErr(GetThreadCurrentTaskRef(&gTaskRef));
  99.  
  100.         FailOSErr(SetDebuggerNotificationProcs(
  101.             &ThreadCreatedProc,
  102.             &ThreadDeletedProc,
  103.             &ThreadScheduleProc));
  104.  
  105.         FailNIL(gThreadTable = (ThreadTableHdl) NewHandleClear(sizeofThreadTable(kThreadTableChunk)));
  106.         
  107.         ThreadTablePtr p = *gThreadTable;
  108.         
  109.         p->size            = kThreadTableChunk;
  110.         p->data[0].id    = kApplicationThreadID;
  111.         
  112.         gThreadCount = 1;
  113.     }
  114. }
  115.  
  116. //--------------------------------------------------------------------------------
  117.  
  118. ThreadID ThreadManager::NewThreadID(
  119.     ThreadStyle             threadStyle,
  120.      ThreadEntryProcPtr     threadEntry,
  121.      void *                    threadParam,
  122.      Size                     stackSize,
  123.      ThreadOptions             options,
  124.      void **                threadResult)
  125. {
  126.     ThreadID result;
  127.  
  128.     FailOSErr(::NewThread(threadStyle, threadEntry, threadParam, stackSize, options, threadResult, &result));
  129.     
  130.     return result;
  131. }
  132.  
  133. //--------------------------------------------------------------------------------
  134.  
  135. void* ThreadManager::DisposeThreadID(ThreadID threadToDump)
  136. {
  137.     void* result = nil;
  138.  
  139.     FailOSErr(::DisposeThread(threadToDump, &result, false));
  140.  
  141.     return result;
  142. }
  143.  
  144. //--------------------------------------------------------------------------------
  145.  
  146. void* ThreadManager::RecycleThreadID(ThreadID threadToDump)
  147. {
  148.     void* result = nil;
  149.  
  150.     FailOSErr(::DisposeThread(threadToDump, &result, true));
  151.  
  152.     return result;
  153. }
  154.  
  155. //--------------------------------------------------------------------------------
  156.  
  157. pascal void ThreadManager::ThreadCreatedProc(ThreadID threadCreated)
  158. {
  159.     if (gThreadTable != nil)
  160.     {
  161.         ThreadTablePtr p = *gThreadTable;
  162.         
  163.         int count        = p->size;
  164.         int hole        = hole;
  165.         int index        = -1;
  166.  
  167.         for (int i = 0; i < count; i++)
  168.         {
  169.             ThreadID id = p->data[i].id;
  170.             
  171.             if (id == kNoThreadID)
  172.             {
  173.                 if (hole < 0)
  174.                 {
  175.                     hole = i;
  176.                 }
  177.             }
  178.             else if (id == threadCreated)
  179.             {
  180.                 index = i;
  181.                 break;
  182.             }
  183.         }
  184.         
  185.         if (index < 0)
  186.         {
  187.             if (hole >= 0)
  188.             {
  189.                 index = hole;
  190.             }
  191.             else
  192.             {
  193.                 index = count;
  194.                 count += kThreadTableChunk;
  195.             
  196.                 SetHandleSize((Handle) gThreadTable, sizeofThreadTable(count));
  197.                 
  198.                 FailMemError();
  199.                 
  200.                 p = *gThreadTable;
  201.                 
  202.                 BlockZero(&p->data[index], kThreadTableChunk*sizeof(ThreadTableEntry));
  203.         
  204.                 p->size = count;
  205.             }
  206.             
  207.             p->data[index].id = threadCreated;
  208.         }
  209.     }
  210.  
  211.     gThreadCount++;
  212. }
  213.  
  214. //--------------------------------------------------------------------------------
  215.  
  216. pascal void ThreadManager::ThreadDeletedProc(ThreadID threadDeleted)
  217. {
  218.     if (gThreadTable != nil)
  219.     {
  220.         ThreadTablePtr p = *gThreadTable;
  221.         
  222.         int count = p->size;
  223.  
  224.         for (int i = 0; i < count; i++)
  225.         {
  226.             ThreadID id = p->data[i].id;
  227.             
  228.             if (id == threadDeleted)
  229.             {
  230.                 p->data[i].id    = kNoThreadID;
  231.                 p->data[i].obj    = nil;
  232.                 break;
  233.             }
  234.         }
  235.     }
  236.         
  237.     gThreadCount--;
  238. }
  239.  
  240. //--------------------------------------------------------------------------------
  241.  
  242. pascal ThreadID ThreadManager::ThreadScheduleProc(SchedulerInfoRecPtr schedulerInfo)
  243. {
  244.     return schedulerInfo->SuggestedThreadID;
  245. }
  246.  
  247. //--------------------------------------------------------------------------------
  248.  
  249.