1 /*
2  * Copyright (c) 2005, Eric Crahen
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is furnished
9  * to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in all
12  * copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20  *
21  */
22 
23 #ifndef __ZTMONITOR_H__
24 #define __ZTMONITOR_H__
25 
26 #include "../Status.h"
27 #include "../FastLock.h"
28 
29 namespace ZThread {
30 
31 /**
32  * @class Monitor
33  * @author Eric Crahen <http://www.code-foo.com>
34  * @date <2003-07-18T08:16:09-0400>
35  * @version 2.2.8
36  */
37 class Monitor : public Status, private NonCopyable {
38  private:
39 
40   //! Serialize access to external objects
41   FastLock _lock;
42 
43   //! Condition variable used to block a thread.
44   pthread_cond_t _waitCond;
45 
46   //! Serialize access to the internal state of the monitor
47   pthread_mutex_t _waitLock;
48 
49   //! Owning thread
50   pthread_t _owner;
51 
52   //! Waiting flag, to avoid uneccessary signals
53   volatile bool _waiting;
54 
55  public:
56 
57   typedef Status::STATE STATE;
58 
59   //! Create a new monitor.
60   Monitor();
61 
62   //! Destroy the monitor.
63   ~Monitor();
64 
65   //! Acquire the lock for this monitor.
acquire()66   inline void acquire() {
67     _lock.acquire();
68   }
69 
70   //! Acquire the lock for this monitor.
tryAcquire()71   inline bool tryAcquire() {
72     return _lock.tryAcquire();
73   }
74 
75   //! Release the lock for this monitor
release()76   inline void release() {
77     _lock.release();
78   }
79 
80   /**
81    * Wait for a state change and atomically unlock the external lock.
82    * Blocks for an indefinent amount of time.
83    *
84    * @return INTERRUPTED if the wait was ended by a interrupt()
85    *         or SIGNALED if the wait was ended by a notify()
86    *
87    * @post the external lock is always acquired before this function returns
88    */
wait()89   inline STATE wait() {
90     return wait(0);
91   }
92 
93   /**
94    * Wait for a state change and atomically unlock the external lock.
95    * May blocks for an indefinent amount of time.
96    *
97    * @param timeout - maximum time to block (milliseconds) or 0 to
98    * block indefinently
99    *
100    * @return INTERRUPTED if the wait was ended by a interrupt()
101    *         or TIMEDOUT if the maximum wait time expired.
102    *         or SIGNALED if the wait was ended by a notify()
103    *
104    * @post the external lock is always acquired before this function returns
105    */
106   STATE wait(unsigned long timeout);
107 
108   /**
109    * Interrupt this monitor. If there is a thread blocked on this monitor object
110    * it will be signaled and released. If there is no waiter, a flag is set and
111    * the next attempt to wait() will return INTERRUPTED w/o blocking.
112    *
113    * @return false if the thread was previously INTERRUPTED.
114    */
115   bool interrupt();
116 
117   /**
118    * Notify this monitor. If there is a thread blocked on this monitor object
119    * it will be signaled and released. If there is no waiter, a flag is set and
120    * the next attempt to wait() will return SIGNALED w/o blocking, if no other
121    * flag is set.
122    *
123    * @return false if the thread was previously INTERRUPTED.
124    */
125   bool notify();
126 
127   /**
128    * Check the state of this monitor, clearing the INTERRUPTED status if set.
129    *
130    * @return bool true if the monitor was INTERRUPTED.
131    * @post INTERRUPTED flag cleared if the calling thread owns the monitor.
132    */
133   bool isInterrupted();
134 
135   /**
136    * Mark the Status CANCELED, and INTERRUPT the montor.
137    *
138    * @see interrupt()
139    */
140   bool cancel();
141 
142   /**
143    * Test the CANCELED Status, clearing the INTERRUPTED status if set.
144    *
145    * @return bool
146    */
147   bool isCanceled();
148 
149 };
150 
151 };
152 
153 #endif
154