]> rtime.felk.cvut.cz Git - eurobot/public.git/blob - src/boost/boost/thread/pthread/recursive_mutex.hpp
Add subset of boost library headers needed for compilation on PowerPC
[eurobot/public.git] / src / boost / boost / thread / pthread / recursive_mutex.hpp
1 #ifndef BOOST_THREAD_PTHREAD_RECURSIVE_MUTEX_HPP
2 #define BOOST_THREAD_PTHREAD_RECURSIVE_MUTEX_HPP
3 // (C) Copyright 2007-8 Anthony Williams
4 // Distributed under the Boost Software License, Version 1.0. (See
5 // accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7
8 #include <pthread.h>
9 #include <boost/utility.hpp>
10 #include <boost/throw_exception.hpp>
11 #include <boost/thread/exceptions.hpp>
12 #include <boost/thread/locks.hpp>
13 #include <boost/thread/thread_time.hpp>
14 #include <boost/assert.hpp>
15 #ifndef _WIN32
16 #include <unistd.h>
17 #endif
18 #include <boost/date_time/posix_time/conversion.hpp>
19 #include <errno.h>
20 #include <boost/thread/pthread/timespec.hpp>
21 #include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
22
23 #ifdef _POSIX_TIMEOUTS
24 #if _POSIX_TIMEOUTS >= 0
25 #define BOOST_PTHREAD_HAS_TIMEDLOCK
26 #endif
27 #endif
28
29 #if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE) && defined(BOOST_PTHREAD_HAS_TIMEDLOCK)
30 #define BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
31 #endif
32
33 #include <boost/config/abi_prefix.hpp>
34
35 namespace boost
36 {
37     class recursive_mutex
38     {
39     private:
40         recursive_mutex(recursive_mutex const&);
41         recursive_mutex& operator=(recursive_mutex const&);
42         pthread_mutex_t m;
43 #ifndef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
44         pthread_cond_t cond;
45         bool is_locked;
46         pthread_t owner;
47         unsigned count;
48 #endif
49     public:
50         recursive_mutex()
51         {
52 #ifdef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
53             pthread_mutexattr_t attr;
54
55             int const init_attr_res=pthread_mutexattr_init(&attr);
56             if(init_attr_res)
57             {
58                 boost::throw_exception(thread_resource_error());
59             }
60             int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
61             if(set_attr_res)
62             {
63                 BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
64                 boost::throw_exception(thread_resource_error());
65             }
66
67             int const res=pthread_mutex_init(&m,&attr);
68             if(res)
69             {
70                 BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
71                 boost::throw_exception(thread_resource_error());
72             }
73             BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
74 #else
75             int const res=pthread_mutex_init(&m,NULL);
76             if(res)
77             {
78                 boost::throw_exception(thread_resource_error());
79             }
80             int const res2=pthread_cond_init(&cond,NULL);
81             if(res2)
82             {
83                 BOOST_VERIFY(!pthread_mutex_destroy(&m));
84                 boost::throw_exception(thread_resource_error());
85             }
86             is_locked=false;
87             count=0;
88 #endif
89         }
90         ~recursive_mutex()
91         {
92             BOOST_VERIFY(!pthread_mutex_destroy(&m));
93 #ifndef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
94             BOOST_VERIFY(!pthread_cond_destroy(&cond));
95 #endif
96         }
97
98 #ifdef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
99         void lock()
100         {
101             BOOST_VERIFY(!pthread_mutex_lock(&m));
102         }
103
104         void unlock()
105         {
106             BOOST_VERIFY(!pthread_mutex_unlock(&m));
107         }
108
109         bool try_lock()
110         {
111             int const res=pthread_mutex_trylock(&m);
112             BOOST_ASSERT(!res || res==EBUSY);
113             return !res;
114         }
115         typedef pthread_mutex_t* native_handle_type;
116         native_handle_type native_handle()
117         {
118             return &m;
119         }
120
121 #else
122         void lock()
123         {
124             boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
125             if(is_locked && pthread_equal(owner,pthread_self()))
126             {
127                 ++count;
128                 return;
129             }
130
131             while(is_locked)
132             {
133                 BOOST_VERIFY(!pthread_cond_wait(&cond,&m));
134             }
135             is_locked=true;
136             ++count;
137             owner=pthread_self();
138         }
139
140         void unlock()
141         {
142             boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
143             if(!--count)
144             {
145                 is_locked=false;
146             }
147             BOOST_VERIFY(!pthread_cond_signal(&cond));
148         }
149
150         bool try_lock()
151         {
152             boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
153             if(is_locked && !pthread_equal(owner,pthread_self()))
154             {
155                 return false;
156             }
157             is_locked=true;
158             ++count;
159             owner=pthread_self();
160             return true;
161         }
162
163 #endif
164
165         typedef unique_lock<recursive_mutex> scoped_lock;
166         typedef detail::try_lock_wrapper<recursive_mutex> scoped_try_lock;
167     };
168
169     typedef recursive_mutex recursive_try_mutex;
170
171     class recursive_timed_mutex
172     {
173     private:
174         recursive_timed_mutex(recursive_timed_mutex const&);
175         recursive_timed_mutex& operator=(recursive_timed_mutex const&);
176     private:
177         pthread_mutex_t m;
178 #ifndef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
179         pthread_cond_t cond;
180         bool is_locked;
181         pthread_t owner;
182         unsigned count;
183 #endif
184     public:
185         recursive_timed_mutex()
186         {
187 #ifdef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
188             pthread_mutexattr_t attr;
189
190             int const init_attr_res=pthread_mutexattr_init(&attr);
191             if(init_attr_res)
192             {
193                 boost::throw_exception(thread_resource_error());
194             }
195             int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
196             if(set_attr_res)
197             {
198                 boost::throw_exception(thread_resource_error());
199             }
200
201             int const res=pthread_mutex_init(&m,&attr);
202             if(res)
203             {
204                 BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
205                 boost::throw_exception(thread_resource_error());
206             }
207             BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
208 #else
209             int const res=pthread_mutex_init(&m,NULL);
210             if(res)
211             {
212                 boost::throw_exception(thread_resource_error());
213             }
214             int const res2=pthread_cond_init(&cond,NULL);
215             if(res2)
216             {
217                 BOOST_VERIFY(!pthread_mutex_destroy(&m));
218                 boost::throw_exception(thread_resource_error());
219             }
220             is_locked=false;
221             count=0;
222 #endif
223         }
224         ~recursive_timed_mutex()
225         {
226             BOOST_VERIFY(!pthread_mutex_destroy(&m));
227 #ifndef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
228             BOOST_VERIFY(!pthread_cond_destroy(&cond));
229 #endif
230         }
231
232         template<typename TimeDuration>
233         bool timed_lock(TimeDuration const & relative_time)
234         {
235             return timed_lock(get_system_time()+relative_time);
236         }
237
238 #ifdef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK
239         void lock()
240         {
241             BOOST_VERIFY(!pthread_mutex_lock(&m));
242         }
243
244         void unlock()
245         {
246             BOOST_VERIFY(!pthread_mutex_unlock(&m));
247         }
248
249         bool try_lock()
250         {
251             int const res=pthread_mutex_trylock(&m);
252             BOOST_ASSERT(!res || res==EBUSY);
253             return !res;
254         }
255         bool timed_lock(system_time const & abs_time)
256         {
257             struct timespec const timeout=detail::get_timespec(abs_time);
258             int const res=pthread_mutex_timedlock(&m,&timeout);
259             BOOST_ASSERT(!res || res==ETIMEDOUT);
260             return !res;
261         }
262
263         typedef pthread_mutex_t* native_handle_type;
264         native_handle_type native_handle()
265         {
266             return &m;
267         }
268
269 #else
270         void lock()
271         {
272             boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
273             if(is_locked && pthread_equal(owner,pthread_self()))
274             {
275                 ++count;
276                 return;
277             }
278
279             while(is_locked)
280             {
281                 BOOST_VERIFY(!pthread_cond_wait(&cond,&m));
282             }
283             is_locked=true;
284             ++count;
285             owner=pthread_self();
286         }
287
288         void unlock()
289         {
290             boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
291             if(!--count)
292             {
293                 is_locked=false;
294             }
295             BOOST_VERIFY(!pthread_cond_signal(&cond));
296         }
297
298         bool try_lock()
299         {
300             boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
301             if(is_locked && !pthread_equal(owner,pthread_self()))
302             {
303                 return false;
304             }
305             is_locked=true;
306             ++count;
307             owner=pthread_self();
308             return true;
309         }
310
311         bool timed_lock(system_time const & abs_time)
312         {
313             struct timespec const timeout=detail::get_timespec(abs_time);
314             boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
315             if(is_locked && pthread_equal(owner,pthread_self()))
316             {
317                 ++count;
318                 return true;
319             }
320             while(is_locked)
321             {
322                 int const cond_res=pthread_cond_timedwait(&cond,&m,&timeout);
323                 if(cond_res==ETIMEDOUT)
324                 {
325                     return false;
326                 }
327                 BOOST_ASSERT(!cond_res);
328             }
329             is_locked=true;
330             ++count;
331             owner=pthread_self();
332             return true;
333         }
334 #endif
335
336         typedef unique_lock<recursive_timed_mutex> scoped_timed_lock;
337         typedef detail::try_lock_wrapper<recursive_timed_mutex> scoped_try_lock;
338         typedef scoped_timed_lock scoped_lock;
339     };
340
341 }
342
343 #include <boost/config/abi_suffix.hpp>
344
345 #endif