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