PageRenderTime 36ms CodeModel.GetById 16ms app.highlight 16ms RepoModel.GetById 1ms app.codeStats 0ms

/src/contrib/boost/thread/pthread/recursive_mutex.hpp

http://pythonocc.googlecode.com/
C++ Header | 267 lines | 234 code | 29 blank | 4 comment | 19 complexity | 0ff70cdd565f5ca258649d8f3ed1f93a MD5 | raw file
  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 "timespec.hpp"
 21#include "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#include <boost/config/abi_prefix.hpp>
 30
 31namespace boost
 32{
 33    class recursive_mutex:
 34        boost::noncopyable
 35    {
 36    private:
 37        pthread_mutex_t m;
 38    public:
 39        recursive_mutex()
 40        {
 41            pthread_mutexattr_t attr;
 42            
 43            int const init_attr_res=pthread_mutexattr_init(&attr);
 44            if(init_attr_res)
 45            {
 46                boost::throw_exception(thread_resource_error());
 47            }
 48            int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
 49            if(set_attr_res)
 50            {
 51                boost::throw_exception(thread_resource_error());
 52            }
 53            
 54            int const res=pthread_mutex_init(&m,&attr);
 55            if(res)
 56            {
 57                boost::throw_exception(thread_resource_error());
 58            }
 59            BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
 60        }
 61        ~recursive_mutex()
 62        {
 63            BOOST_VERIFY(!pthread_mutex_destroy(&m));
 64        }
 65        
 66        void lock()
 67        {
 68            BOOST_VERIFY(!pthread_mutex_lock(&m));
 69        }
 70
 71        void unlock()
 72        {
 73            BOOST_VERIFY(!pthread_mutex_unlock(&m));
 74        }
 75        
 76        bool try_lock()
 77        {
 78            int const res=pthread_mutex_trylock(&m);
 79            BOOST_ASSERT(!res || res==EBUSY);
 80            return !res;
 81        }
 82
 83        typedef pthread_mutex_t* native_handle_type;
 84        native_handle_type native_handle()
 85        {
 86            return &m;
 87        }
 88
 89        typedef unique_lock<recursive_mutex> scoped_lock;
 90        typedef detail::try_lock_wrapper<recursive_mutex> scoped_try_lock;
 91    };
 92
 93    typedef recursive_mutex recursive_try_mutex;
 94
 95    class recursive_timed_mutex:
 96        boost::noncopyable
 97    {
 98    private:
 99        pthread_mutex_t m;
100#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
101        pthread_cond_t cond;
102        bool is_locked;
103        pthread_t owner;
104        unsigned count;
105#endif
106    public:
107        recursive_timed_mutex()
108        {
109#ifdef BOOST_PTHREAD_HAS_TIMEDLOCK
110            pthread_mutexattr_t attr;
111            
112            int const init_attr_res=pthread_mutexattr_init(&attr);
113            if(init_attr_res)
114            {
115                boost::throw_exception(thread_resource_error());
116            }
117            int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
118            if(set_attr_res)
119            {
120                boost::throw_exception(thread_resource_error());
121            }
122            
123            int const res=pthread_mutex_init(&m,&attr);
124            if(res)
125            {
126                BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
127                boost::throw_exception(thread_resource_error());
128            }
129            BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
130#else
131            int const res=pthread_mutex_init(&m,NULL);
132            if(res)
133            {
134                boost::throw_exception(thread_resource_error());
135            }
136            int const res2=pthread_cond_init(&cond,NULL);
137            if(res2)
138            {
139                BOOST_VERIFY(!pthread_mutex_destroy(&m));
140                boost::throw_exception(thread_resource_error());
141            }
142            is_locked=false;
143            count=0;
144#endif
145        }
146        ~recursive_timed_mutex()
147        {
148            BOOST_VERIFY(!pthread_mutex_destroy(&m));
149#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
150            BOOST_VERIFY(!pthread_cond_destroy(&cond));
151#endif
152        }
153
154        template<typename TimeDuration>
155        bool timed_lock(TimeDuration const & relative_time)
156        {
157            return timed_lock(get_system_time()+relative_time);
158        }
159
160#ifdef BOOST_PTHREAD_HAS_TIMEDLOCK
161        void lock()
162        {
163            BOOST_VERIFY(!pthread_mutex_lock(&m));
164        }
165
166        void unlock()
167        {
168            BOOST_VERIFY(!pthread_mutex_unlock(&m));
169        }
170        
171        bool try_lock()
172        {
173            int const res=pthread_mutex_trylock(&m);
174            BOOST_ASSERT(!res || res==EBUSY);
175            return !res;
176        }
177        bool timed_lock(system_time const & abs_time)
178        {
179            struct timespec const timeout=detail::get_timespec(abs_time);
180            int const res=pthread_mutex_timedlock(&m,&timeout);
181            BOOST_ASSERT(!res || res==ETIMEDOUT);
182            return !res;
183        }
184
185        typedef pthread_mutex_t* native_handle_type;
186        native_handle_type native_handle()
187        {
188            return &m;
189        }
190
191#else
192        void lock()
193        {
194            boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
195            if(is_locked && pthread_equal(owner,pthread_self()))
196            {
197                ++count;
198                return;
199            }
200            
201            while(is_locked)
202            {
203                BOOST_VERIFY(!pthread_cond_wait(&cond,&m));
204            }
205            is_locked=true;
206            ++count;
207            owner=pthread_self();
208        }
209
210        void unlock()
211        {
212            boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
213            if(!--count)
214            {
215                is_locked=false;
216            }
217            BOOST_VERIFY(!pthread_cond_signal(&cond));
218        }
219        
220        bool try_lock()
221        {
222            boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
223            if(is_locked && !pthread_equal(owner,pthread_self()))
224            {
225                return false;
226            }
227            is_locked=true;
228            ++count;
229            owner=pthread_self();
230            return true;
231        }
232
233        bool timed_lock(system_time const & abs_time)
234        {
235            struct timespec const timeout=detail::get_timespec(abs_time);
236            boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
237            if(is_locked && pthread_equal(owner,pthread_self()))
238            {
239                ++count;
240                return true;
241            }
242            while(is_locked)
243            {
244                int const cond_res=pthread_cond_timedwait(&cond,&m,&timeout);
245                if(cond_res==ETIMEDOUT)
246                {
247                    return false;
248                }
249                BOOST_ASSERT(!cond_res);
250            }
251            is_locked=true;
252            ++count;
253            owner=pthread_self();
254            return true;
255        }
256#endif
257
258        typedef unique_lock<recursive_timed_mutex> scoped_timed_lock;
259        typedef detail::try_lock_wrapper<recursive_timed_mutex> scoped_try_lock;
260        typedef scoped_timed_lock scoped_lock;
261    };
262
263}
264
265#include <boost/config/abi_suffix.hpp>
266
267#endif