aae15ed85adc88be5a0788f9aae465a1d962d94c
[shibboleth/cpp-xmltooling.git] / xmltooling / util / Threads.h
1 /*
2  *  Copyright 2001-2010 Internet2
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /**
18  * @file xmltooling/util/Threads.h
19  *
20  * Thread and locking wrappers.
21  */
22
23 #ifndef _xmltooling_threads_h
24 #define _xmltooling_threads_h
25
26 #include <xmltooling/exceptions.h>
27
28 #include <signal.h>
29
30 namespace xmltooling
31 {
32     DECL_XMLTOOLING_EXCEPTION(ThreadingException,XMLTOOL_EXCEPTIONAPI(XMLTOOL_API),xmltooling,XMLToolingException,Exceptions during threading/locking operations);
33
34     /**
35      * A class for manual thread creation and synchronization.
36      */
37     class XMLTOOL_API Thread
38     {
39         MAKE_NONCOPYABLE(Thread);
40     protected:
41         Thread() {}
42     public:
43         virtual ~Thread() {}
44
45         /**
46          * Disassociate from the thread.
47          *
48          * @return 0 for success, non-zero for failure
49          */
50         virtual int detach()=0;
51
52         /**
53          * Join with the thread and wait for its completion.
54          *
55          * @param thread_return holds the return value of the thread routine
56          * @return 0 for success, non-zero for failure
57          */
58         virtual int join(void** thread_return)=0;
59
60         /**
61          * Kill the thread.
62          *
63          * @param signo the signal to send to the thread
64          * @return 0 for success, non-zero for failure
65          */
66         virtual int kill(int signo)=0;
67
68         /**
69          * Creates a new thread object to run the supplied start routine.
70          *
71          * @param start_routine the function to execute on the thread
72          * @param arg           a parameter for the start routine
73          * @param stacksize     size of stack to use, or 0 for default
74          * @return  the created and running thread object
75          */
76         static Thread* create(void* (*start_routine)(void*), void* arg, size_t stacksize=0);
77
78         /**
79          * Exits a thread gracefully.
80          *
81          * @param return_val    the return value for the thread
82          */
83         static void exit(void* return_val);
84
85         /**
86          * Sleeps the current thread for the specified amount of time.
87          *
88          * @param seconds   time to sleep
89          */
90         static void sleep(int seconds);
91 #ifndef WIN32
92         /**
93          * Masks all signals from a thread.
94          */
95         static void mask_all_signals(void);
96
97         /**
98          * Masks specific signals from a thread.
99          *
100          * @param how
101          * @param newmask   the new signal mask
102          * @param oldmask   the old signal mask
103          * @return 0 for success, non-zero for failure
104          */
105         static int mask_signals(int how, const sigset_t *newmask, sigset_t *oldmask);
106 #endif
107     };
108
109     /**
110      * A class for managing Thread Local Storage values.
111      */
112     class XMLTOOL_API ThreadKey
113     {
114         MAKE_NONCOPYABLE(ThreadKey);
115     protected:
116         ThreadKey() {}
117     public:
118         virtual ~ThreadKey() {}
119
120         /**
121          * Sets the value for a TLS key.
122          *
123          * @param data  the value to set
124          * @return 0 for success, non-zero for failure
125          */
126         virtual int setData(void* data)=0;
127
128         /**
129          * Returns the value for a TLS key.
130          *
131          * @return the value or nullptr
132          */
133         virtual void* getData() const=0;
134
135         /**
136          * Creates a new TLS key.
137          *
138          * @param destroy_fn    a functon to cleanup key values
139          * @return the new key
140          */
141         static ThreadKey* create(void (*destroy_fn)(void*));
142
143 #ifdef WIN32
144         /**
145          * Allows system to notify TLS implementation when a thread completes.
146          *
147          * <p>Windows doesn't support TLS destructors, so only the DllMain detach
148          * notification can be used to trigger per-thread cleanup.
149          */
150         static void onDetach();
151 #endif
152     };
153
154     /**
155      * A class for managing exclusive access to resources.
156      */
157     class XMLTOOL_API Mutex
158     {
159         MAKE_NONCOPYABLE(Mutex);
160     protected:
161         Mutex() {}
162     public:
163         virtual ~Mutex() {}
164
165         /**
166          * Locks the mutex for exclusive access.
167          *
168          * @return 0 for success, non-zero for failure
169          */
170         virtual int lock()=0;
171
172         /**
173          * Unlocks the mutex for exclusive access.
174          *
175          * @return 0 for success, non-zero for failure
176          */
177         virtual int unlock()=0;
178
179         /**
180          * Creates a new mutex object.
181          *
182          * @return the new mutex
183          */
184         static Mutex* create();
185     };
186
187     /**
188      * A class for managing shared and exclusive access to resources.
189      */
190     class XMLTOOL_API RWLock
191     {
192         MAKE_NONCOPYABLE(RWLock);
193     protected:
194         RWLock() {}
195     public:
196         virtual ~RWLock() {}
197
198         /**
199          * Obtains a shared lock.
200          *
201          * @return 0 for success, non-zero for failure
202          */
203         virtual int rdlock()=0;
204
205         /**
206          * Obtains an exclusive lock.
207          *
208          * @return 0 for success, non-zero for failure
209          */
210         virtual int wrlock()=0;
211
212         /**
213          * Unlocks the lock.
214          *
215          * @return 0 for success, non-zero for failure
216          */
217         virtual int unlock()=0;
218
219         /**
220          * Creates a new read/write lock.
221          *
222          * @return the new lock
223          */
224         static RWLock* create();
225     };
226
227     /**
228      * A class for establishing queues on a mutex based on a periodic condition.
229      */
230     class XMLTOOL_API CondWait
231     {
232         MAKE_NONCOPYABLE(CondWait);
233     protected:
234         CondWait() {}
235     public:
236         virtual ~CondWait() {}
237
238         /**
239          * Waits for a condition variable using the supplied mutex as a queue.
240          *
241          * @param lock  mutex to queue on
242          * @return 0 for success, non-zero for failure
243          */
244         virtual int wait(Mutex* lock)=0;
245
246         /**
247          * Waits for a condition variable using the supplied mutex as a queue,
248          * but only for a certain time limit.
249          *
250          * @param lock          mutex to queue on
251          * @param delay_seconds maximum time to wait before waking up
252          * @return 0 for success, non-zero for failure
253          */
254         virtual int timedwait(Mutex* lock, int delay_seconds)=0;
255
256         /**
257          * Signal a single thread to wake up if a condition changes.
258          *
259          * @return 0 for success, non-zero for failure
260          */
261         virtual int signal()=0;
262
263         /**
264          * Signal all threads to wake up if a condition changes.
265          *
266          * @return 0 for success, non-zero for failure
267          */
268         virtual int broadcast()=0;
269
270         /**
271          * Creates a new condition variable.
272          *
273          * @return the new condition variable
274          */
275         static CondWait* create();
276     };
277
278     /**
279      * RAII wrapper for a mutex lock.
280      */
281     class XMLTOOL_API Lock {
282         MAKE_NONCOPYABLE(Lock);
283     public:
284         /**
285          * Locks and wraps the designated mutex.
286          *
287          * @param mtx mutex to lock
288          */
289         Lock(Mutex* mtx) : mutex(mtx) {
290             if (mutex)
291                 mutex->lock();
292         }
293
294         /**
295          * Unlocks the wrapped mutex.
296          */
297         ~Lock() {
298             if (mutex)
299                 mutex->unlock();
300         }
301
302     private:
303         Mutex* mutex;
304     };
305
306     /**
307      * RAII wrapper for a shared lock.
308      */
309     class XMLTOOL_API SharedLock {
310         MAKE_NONCOPYABLE(SharedLock);
311     public:
312         /**
313          * Locks and wraps the designated shared lock.
314          *
315          * @param lock      lock to acquire
316          * @param lockit    true if the lock should be acquired here, false if already acquired
317          */
318         SharedLock(RWLock* lock, bool lockit=true) : rwlock(lock) {
319             if (rwlock && lockit)
320                 rwlock->rdlock();
321         }
322
323         /**
324          * Unlocks the wrapped shared lock.
325          */
326         ~SharedLock() {
327             if (rwlock)
328                 rwlock->unlock();
329         }
330
331     private:
332         RWLock* rwlock;
333     };
334
335 }
336
337 #endif /* _xmltooling_threads_h */