1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
4 // Software License, Version 1.0. (See accompanying file
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // See http://www.boost.org/libs/interprocess for documentation.
8 //
9 //////////////////////////////////////////////////////////////////////////////
10 
11 #ifndef BOOST_INTERPROCESS_PTHREAD_HELPERS_HPP
12 #define BOOST_INTERPROCESS_PTHREAD_HELPERS_HPP
13 
14 #ifndef BOOST_CONFIG_HPP
15 #  include <boost/config.hpp>
16 #endif
17 #
18 #if defined(BOOST_HAS_PRAGMA_ONCE)
19 #  pragma once
20 #endif
21 
22 #include <boost/interprocess/detail/config_begin.hpp>
23 #include <boost/interprocess/detail/workaround.hpp>
24 
25 #include <pthread.h>
26 #include <errno.h>
27 #include <boost/interprocess/exceptions.hpp>
28 
29 namespace boost {
30 namespace interprocess {
31 namespace ipcdetail{
32 
33    #if defined BOOST_INTERPROCESS_POSIX_PROCESS_SHARED
34 
35    //!Makes pthread_mutexattr_t cleanup easy when using exceptions
36    struct mutexattr_wrapper
37    {
38       //!Constructor
39       mutexattr_wrapper(bool recursive = false)
40       {
41          if(pthread_mutexattr_init(&m_attr)!=0 ||
42             pthread_mutexattr_setpshared(&m_attr, PTHREAD_PROCESS_SHARED)!= 0 ||
43              (recursive &&
44               pthread_mutexattr_settype(&m_attr, PTHREAD_MUTEX_RECURSIVE)!= 0 ))
45             throw interprocess_exception("pthread_mutexattr_xxxx failed");
46       }
47 
48       //!Destructor
49      ~mutexattr_wrapper()  {  pthread_mutexattr_destroy(&m_attr);  }
50 
51       //!This allows using mutexattr_wrapper as pthread_mutexattr_t
52       operator pthread_mutexattr_t&()  {  return m_attr;  }
53 
54       pthread_mutexattr_t m_attr;
55    };
56 
57    //!Makes pthread_condattr_t cleanup easy when using exceptions
58    struct condattr_wrapper
59    {
60       //!Constructor
61       condattr_wrapper()
62       {
63          if(pthread_condattr_init(&m_attr)!=0 ||
64             pthread_condattr_setpshared(&m_attr, PTHREAD_PROCESS_SHARED)!= 0)
65             throw interprocess_exception("pthread_condattr_xxxx failed");
66       }
67 
68       //!Destructor
69      ~condattr_wrapper() { pthread_condattr_destroy(&m_attr); }
70 
71       //!This allows using condattr_wrapper as pthread_condattr_t
72       operator pthread_condattr_t&(){  return m_attr;  }
73 
74       pthread_condattr_t m_attr;
75    };
76 
77    //!Makes initialized pthread_mutex_t cleanup easy when using exceptions
78    class mutex_initializer
79    {
80     public:
81       //!Constructor. Takes interprocess_mutex attributes to initialize the interprocess_mutex
82       mutex_initializer(pthread_mutex_t &mut, pthread_mutexattr_t &mut_attr)
83       : mp_mut(&mut)
84       {
85          if(pthread_mutex_init(mp_mut, &mut_attr) != 0)
86             throw interprocess_exception("pthread_mutex_init failed");
87       }
88 
89      ~mutex_initializer() {  if(mp_mut) pthread_mutex_destroy(mp_mut);  }
90 
91       void release() {mp_mut = 0; }
92 
93     private:
94       pthread_mutex_t *mp_mut;
95    };
96 
97    //!Makes initialized pthread_cond_t cleanup easy when using exceptions
98    class condition_initializer
99    {
100     public:
101       condition_initializer(pthread_cond_t &cond, pthread_condattr_t &cond_attr)
102       : mp_cond(&cond)
103       {
104          if(pthread_cond_init(mp_cond, &cond_attr)!= 0)
105             throw interprocess_exception("pthread_cond_init failed");
106       }
107 
108      ~condition_initializer()   {  if(mp_cond) pthread_cond_destroy(mp_cond);  }
109 
110       void release()       { mp_cond = 0; }
111 
112     private:
113       pthread_cond_t *mp_cond;
114    };
115 
116    #endif   //   #if defined BOOST_INTERPROCESS_POSIX_PROCESS_SHARED
117 
118    #if defined(BOOST_INTERPROCESS_POSIX_BARRIERS) && defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED)
119 
120    //!Makes pthread_barrierattr_t cleanup easy when using exceptions
121    struct barrierattr_wrapper
122    {
123       //!Constructor
124       barrierattr_wrapper()
125       {
126          if(pthread_barrierattr_init(&m_attr)!=0 ||
127             pthread_barrierattr_setpshared(&m_attr, PTHREAD_PROCESS_SHARED)!= 0)
128             throw interprocess_exception("pthread_barrierattr_xxx failed");
129       }
130 
131       //!Destructor
132      ~barrierattr_wrapper()  {  pthread_barrierattr_destroy(&m_attr);  }
133 
134       //!This allows using mutexattr_wrapper as pthread_barrierattr_t
135       operator pthread_barrierattr_t&()  {  return m_attr;  }
136 
137       pthread_barrierattr_t m_attr;
138    };
139 
140    //!Makes initialized pthread_barrier_t cleanup easy when using exceptions
141    class barrier_initializer
142    {
143     public:
144       //!Constructor. Takes barrier attributes to initialize the barrier
145       barrier_initializer(pthread_barrier_t &mut,
146                           pthread_barrierattr_t &mut_attr,
147                           int count)
148       : mp_barrier(&mut)
149       {
150          if(pthread_barrier_init(mp_barrier, &mut_attr, count) != 0)
151             throw interprocess_exception("pthread_barrier_init failed");
152       }
153 
154      ~barrier_initializer() {  if(mp_barrier) pthread_barrier_destroy(mp_barrier);  }
155 
156       void release() {mp_barrier = 0; }
157 
158     private:
159       pthread_barrier_t *mp_barrier;
160    };
161 
162    #endif   //#if defined(BOOST_INTERPROCESS_POSIX_BARRIERS) && defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED)
163 
164 }//namespace ipcdetail
165 
166 }//namespace interprocess
167 
168 }//namespace boost
169 
170 #include <boost/interprocess/detail/config_end.hpp>
171 
172 #endif //ifdef BOOST_INTERPROCESS_PTHREAD_HELPERS_HPP
173