sigx++  2.0.1
lockable.h
Go to the documentation of this file.
1 #ifndef _SIGX_LOCKABLE_H_
2 #define _SIGX_LOCKABLE_H_
3 
4 /*
5  * Copyright 2008 Klaus Triendl
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the Free
19  * Software Foundation, 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21 */
22 
23 /*
24  * Inspired by Andrei Alexandrescu's article "volatile - Multithreaded
25  * Programmer's Best Friend":
26  * http://www.ddj.com/dept/cpp/184403766
27 */
28 
29 #include <tr1/type_traits>
30 #include <sigx/noncopyable.h>
31 #include <sigx/lockable_fwddecl.h>
32 #include <sigx/const_trait.h>
33 #include <sigx/volatile_trait.h>
34 
35 
36 namespace sigx
37 {
38 
50 template<typename T_mutex>
52 {
53  typedef T_mutex mutex_type;
54 
55 
56  mutex_type& mutex() const throw()
57  {
58  return m_mutex;
59  }
60 
61 protected:
63  m_mutex()
64  {}
65 
66 
70 };
71 
72 
73 
90 template<typename T_type, typename T_mutex>
91 struct safe_lockable: public lockable_base<T_mutex>
92 {
93  // lock_acquirer can use interface methods
94  template<locking_policy I_policy, typename T_type1, typename T_mutex1, typename T_islockable> friend class lock_acquirer;
95 
97  // acquired_type = type to protect, 1:1 from T_type
98  typedef T_type acquired_type;
99  // volatile_type = make T_type volatile, even if T_type is a reference
100  // volatile T_type or volatile T_type&
102  // reference_type = reference to volatile-stripped T_type
103  // T_type&
104  typedef typename std::tr1::add_reference<typename volatile_trait<acquired_type>::remove>::type reference_type;
105  // volatile_reference_type = reference to volatile T_type, even if T_type is a reference
106  // volatile T_type&
107  typedef typename std::tr1::add_reference<volatile_type>::type volatile_reference_type;
108  // reference_type = reference to volatile-stripped T_type, even if T_type is a reference
109  // const T_type&
110  typedef typename std::tr1::add_reference<typename const_trait<reference_type>::add>::type const_reference_type;
111  // cv_reference_type = reference to cv-qualified T_type, even if T_type is a reference
112  // const volatile T_type&
113  typedef typename std::tr1::add_reference<typename const_trait<volatile_type>::add>::type cv_reference_type;
114  // apply const qualifier and reference to toplevel type, unchanged if toplevel type is a reference
115  typedef typename std::tr1::add_reference<typename std::tr1::add_const<acquired_type>::type>::type toplevel_const_reference_type;
116 
117 
123  parent_type(),
124  m_obj()
125  {}
126 
130  parent_type(),
131  m_obj(_a_value)
132  {}
133 
134 
135 protected:
139  {
140  return m_obj;
141  }
142 
146  {
147  // volatile_cast m_obj
148  return const_cast<reference_type>(m_obj);
149  }
150 
154  {
155  return m_obj;
156  }
157 
161  {
162  // volatile_cast m_obj
163  return const_cast<const_reference_type>(m_obj);
164  }
165 
166 
167 private:
170  volatile_type m_obj;
171 };
172 
173 
176 template<typename T_type, typename T_mutex>
177 struct lockable: public safe_lockable<T_type, T_mutex>
178 {
181 
182 public:
188  parent_type()
189  {}
190 
194  parent_type(_a_value)
195  {}
196 
197  // make safe_lockable's interface publicly available
200 };
201 
202 
203 
204 #if 0 // specializations for pointers
205 
214 template<typename T_mutex>
215 struct lockable<void*, T_mutex>: public lockable_base<T_mutex>
216 {
217  typedef void* acquired_type;
218  typedef T_mutex mutex_type;
219  typedef lockable_base<mutex_type> parent_type;
220  typedef lockable<acquired_type, mutex_type> type;
221  typedef typename volatile_trait<acquired_type>::add volatile_type;
222  typedef typename std::tr1::add_reference<typename volatile_trait<acquired_type>::remove>::type reference_type;
223  typedef typename std::tr1::add_reference<typename volatile_trait<acquired_type>::add>::type volatile_reference_type;
224  typedef typename std::tr1::add_reference<typename std::tr1::add_const<acquired_type>::type>::type take_type;
225 
226 
231  lockable(take_type _a_value = 0):
232  parent_type(),
233  m_obj(_a_value)
234  {}
235 
238  volatile_reference_type access_volatile()
239  {
240  return m_obj;
241  }
242 
245  reference_type access_nonvolatile()
246  {
247  // volatile_cast m_obj
248  return const_cast<reference_type>(m_obj);
249  }
250 
251 
252 private:
255  volatile_type m_obj;
256 };
257 
258 
259 
270 template<typename T_type, typename T_mutex>
271 struct lockable<T_type*, T_mutex>: public lockable<void*, T_mutex>
272 {
273  typedef lockable<void*, T_mutex> parent_type;
274  typedef T_type* acquired_type;
275  typedef lockable<acquired_type, mutex_type> type;
276  typedef typename volatile_trait<acquired_type>::add volatile_type;
277  typedef typename std::tr1::add_reference<typename volatile_trait<acquired_type>::remove>::type reference_type;
278  typedef typename std::tr1::add_reference<typename volatile_trait<acquired_type>::add>::type volatile_reference_type;
279  typedef typename std::tr1::add_reference<typename std::tr1::add_const<acquired_type>::type>::type take_type;
280 
281 
286  lockable(take_type _a_value = 0):
287  parent_type((void*&) _a_value)
288  {}
289 
295  volatile_reference_type access_volatile()
296  {
297  return (volatile_reference_type) parent_type::access_volatile();
298  }
299 
302  reference_type access_acquiree()
303  {
304  return (reference_type) parent_type::access_acquiree();
305  }
306 };
307 #endif
308 
309 
310 
311 // @addtogroup threadsafety
315 } // namespace sigx
316 
317 
318 #endif // end file guard