home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1998 / MacHack 1998.toast / Papers / C++ Exceptions / µShell / Threads Support / Semaphores.h < prev    next >
Encoding:
C/C++ Source or Header  |  1996-01-13  |  5.7 KB  |  142 lines  |  [TEXT/CWIE]

  1. #ifndef __SEMAPHORES__
  2. #define __SEMAPHORES__
  3.  
  4. #ifndef __THREADS__
  5. #include <Threads.h>
  6. #endif
  7.  
  8.  
  9. //========================================================================================
  10. // CLASS TThreadIDQueue
  11. //
  12. // Keep track of a queue of ThreadIDs
  13. //========================================================================================
  14.  
  15. class TThreadIDQueue
  16. {
  17. public:
  18.                     TThreadIDQueue() : fThreadCount(0), fReservedSpace(0), fThreadQueue(nil) {};
  19.                     ~TThreadIDQueue();
  20.     
  21.     OSErr            Enqueue(ThreadID threadToAdd);
  22.     ThreadID        Dequeue();
  23.     long            QueuedThreads() { return fThreadCount; }
  24.     
  25. private:
  26.     OSErr            InsureThreadQueueHasFreeSpace();
  27.  
  28.     long            fThreadCount;
  29.     long            fReservedSpace;
  30.     ThreadID**        fThreadQueue;
  31. };
  32.  
  33. enum
  34. {
  35.     kAnySemaphoreID = 0,
  36.     kNeverTimeoutSemaphore = 0x7FFFFFFF
  37. };
  38.  
  39. //========================================================================================
  40. // CLASS TSemaphore
  41. //
  42. // A semaphore consists of an owner thread and a list of blocked threads waiting to
  43. // become the owner.  When the semaphore is created, its resource count is specified
  44. // to be either 0 or 1 (larger numbers could be supported if a list of owning threads
  45. // was kept).
  46. //
  47. //  A thread requests to become the owner by calling Grab, and relinquishes
  48. // ownership by calling Release.  Non-threads can get ownership of the semaphore by 
  49. // calling SetAvailable(false); in this case even though fOwningThread will be nil, the 
  50. // semaphore will still work correctly because fAvailable is false and thus other threads
  51. // that grab the semaphore will block as they should.
  52. //
  53. // Semaphores are linked into a global list of all semaphores upon creation and removed
  54. // upon deletion.  Each semaphore has a unique ID (generated by a static method), and
  55. // the global list can be searched for a given ID (via another static method).
  56. //========================================================================================
  57.  
  58. class TSemaphore
  59. {
  60.     
  61. // --- Methods -------------------------------------------------------------------------------------
  62.  
  63. public:
  64.                             TSemaphore(long resourceCount = 1, long semaphoreID = kAnySemaphoreID);
  65. protected:
  66.     virtual                    ~TSemaphore();
  67.  
  68. public:
  69.     static    void            InitializeGlobals();
  70.     static    long            NewUniqueSemaphoreID();
  71.     static    TSemaphore*        FindSemaphore(long semaphoreID, Boolean createIfNotFound = false, long resourceCount = 1);
  72.     static    void            Idle();
  73.     static    void            ThreadDied(ThreadID threadID);
  74.     static    void            SetDefaultTimeout(long newDefault);
  75.     static    void            SetDefaultMaxWait(long newMaxWait);
  76.     
  77.             void            ReleaseReference();
  78.             void            Dispose();
  79.             long            SemaphoreID() const;
  80.  
  81.             OSErr            Grab(ThreadID threadID = kCurrentThreadID);
  82.             void            Release(ThreadID threadID = kCurrentThreadID);
  83.             ThreadID        ReleaseOneThread();
  84.             void            ReleaseAllThreads();
  85.             Boolean            Available() const;
  86.             void            SetAvailable(Boolean);
  87.             
  88.             void            ResetTimeoutTimer();
  89.             void            AddGracePeriod(long gracePeriod);
  90.             void            SetSemaphoreTimoutValue(long timeoutValue);
  91.             void            SetSemaphoreMaxWaitTime(long timeoutValue);
  92.             long            SemaphoreTimoutValue() { return fSemaphoreTimeoutValue; }
  93.             long            SemaphoreMaxWaitTime() { return fSemaphoreMaxWaitTime; }
  94.             
  95.             unsigned long    TimeoutTick();
  96.             Boolean            CheckIfTimerExpired(unsigned long currentTime);
  97.             void            SemaphoreTimedOut();
  98.             
  99. protected:
  100.             void            RemoveFromGlobalSemaphoreList();
  101.             
  102. // --- Fields -------------------------------------------------------------------------------------
  103.  
  104. private:
  105.     static    TSemaphore*        fgFirstSemaphore;            // Pointer to the first semaphore in the global list of all semaphores
  106.     static    long            fgSemaphoreIDSequence;        // The next available semaphore ID (used for assigning unique IDs)
  107.     static    long            fgSemaphoreDefaultTimeout;    // Default time to wait before timing out
  108.     static    long            fgSemaphoreDefaultMaxWait;    // Default maximum time to wait (exclusive of timer resets)
  109.     static    unsigned long    fgLastTimeoutTest;            // The last tick that we looked for timed-out semaphores
  110.     static    unsigned long    fgLastIdleTick;                // The last tick we got some idle time
  111.     static    unsigned long    fgNextTimeoutTest;            // Next tick to look for semaphores that have timed out
  112.     
  113.             TSemaphore*        fNextSemaphore;                // Previous semaphore in the global list of all semaphores
  114.             TSemaphore*        fPreviousSemaphore;            // Next semaphore in the global list of all semaphores
  115.     
  116.             ThreadID        fOwnerThread;                // The thread that currently owns this semaphore
  117.             TThreadIDQueue    fBlockedThreads;            // Queue of threads blocked on this semaphore
  118.  
  119.             long            fResourceCount;                // The number of threads that may own this semaphore (0 or 1)
  120.             long            fSemaphoreID;                // The ID (usually unique) for this semaphore
  121.             long            fOwnerCount;                // The number of threads that currently own the semaphore (<= fResourceCount)
  122.             Boolean            fDisposed;                    // True if someone disposed this semaphore
  123.             long            fReferenceCount;            // Count of blocked threads, to keep semaphore around after "deletion"
  124.             OSErr            fFailOnWakeup;                // If set, all threads fail with this error when they wake up
  125.             
  126.             unsigned long    fBlockStartTick;            // TickCount at which first thread blocked on this semaphore
  127.             unsigned long    fTimeoutTick;                // The tick at which the semaphore will time out if timer
  128.                                                         // is not recet
  129.             long            fSemaphoreTimeoutValue;        // How long to wait after every timer reset
  130.             long            fSemaphoreMaxWaitTime;        // The maximum number of ticks to wait before ignoring timer
  131.                                                         // resets and just time out
  132. };
  133.  
  134. inline        void            TSemaphore::SetDefaultTimeout(long newDefault)    { fgSemaphoreDefaultTimeout = newDefault; }
  135. inline        void            TSemaphore::SetDefaultMaxWait(long newMaxWait)    { fgSemaphoreDefaultMaxWait = newMaxWait; }
  136. inline        unsigned long    TSemaphore::TimeoutTick()                        { return fTimeoutTick; }
  137.  
  138. inline        long            TSemaphore::SemaphoreID() const        { return fSemaphoreID;     }
  139.  
  140.  
  141. #endif
  142.