00001 #ifndef _SIGX_LOCK_ACQUIRER_H_
00002 #define _SIGX_LOCK_ACQUIRER_H_
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include <tr1/type_traits>
00030 #include <boost/mpl/eval_if.hpp>
00031 #include <boost/mpl/identity.hpp>
00032 #include <sigx/noncopyable.h>
00033
00034 #include <sigx/nonpointeraliasing.h>
00035 #include <sigx/lockable_fwddecl.h>
00036 #include <sigx/choose_lock.h>
00037
00038
00039 namespace sigx
00040 {
00041
00087 template<locking_policy I_policy, typename T_type, typename T_mutex, typename T_islockable>
00088 class lock_acquirer: noncopyable, nonpointeraliasing
00089 {
00090 protected:
00091 typedef T_type acquired_type;
00092 typedef T_mutex mutex_type;
00093
00094 typedef typename std::tr1::remove_reference<acquired_type>::type value_type;
00095
00096 typedef typename boost::mpl::eval_if_c<
00097 I_policy == readlock,
00098 std::tr1::add_const<value_type>,
00099 boost::mpl::identity<value_type>
00100 >::type const_or_value_type;
00101 typedef typename std::tr1::add_reference<typename std::tr1::add_volatile<value_type>::type>::type volatile_reference_type;
00102 typedef typename std::tr1::add_reference<typename std::tr1::remove_volatile<const_or_value_type>::type>::type reference_type;
00103
00109 friend reference_type
00110 access_acquiree(lock_acquirer& l) throw()
00111 {
00112 return l.access_acquiree();
00113 }
00114
00115
00116 public:
00123 lock_acquirer(volatile_reference_type _a_value, mutex_type& _a_mutex):
00124 m_lock(_a_mutex),
00125
00126 m_acquiree(const_cast<reference_type>(_a_value))
00127 {}
00132 template<typename T_lockfwd_arg1>
00133 lock_acquirer(volatile_reference_type _a_value, mutex_type& _a_mutex, T_lockfwd_arg1 lockfwd_arg1):
00134 m_lock(_a_mutex, lockfwd_arg1),
00135
00136 m_acquiree(const_cast<reference_type>(_a_value))
00137 {}
00138
00139
00140 protected:
00143 reference_type access_acquiree() throw()
00144 {
00145 return m_acquiree;
00146 }
00147
00148
00149 protected:
00152 typename choose_lock<mutex_type, I_policy>::type m_lock;
00153
00156 reference_type m_acquiree;
00157 };
00158
00159
00160
00161 template<typename T_type, typename T_mutex, typename T_islockable>
00162 class writelock_acquirer: public lock_acquirer<writelock, T_type, T_mutex, T_islockable>
00163 {
00164 typedef lock_acquirer<writelock, T_type, T_mutex, T_islockable> parent_type;
00165 typedef typename parent_type::mutex_type mutex_type;
00166 typedef typename parent_type::volatile_reference_type volatile_reference_type;
00167
00168 public:
00172 writelock_acquirer(volatile_reference_type _a_value, mutex_type& _a_mutex):
00173 parent_type(_a_value, _a_mutex)
00174 {}
00179 template<typename T_lockfwd_arg1>
00180 writelock_acquirer(volatile_reference_type _a_value, mutex_type& _a_mutex, T_lockfwd_arg1 lockfwd_arg1):
00181 parent_type(_a_value, _a_mutex, lockfwd_arg1)
00182 {}
00183 };
00184
00185 template<typename T_type, typename T_mutex, typename T_islockable>
00186 class readlock_acquirer: public lock_acquirer<readlock, T_type, T_mutex, T_islockable>
00187 {
00188 typedef lock_acquirer<readlock, T_type, T_mutex, T_islockable> parent_type;
00189 typedef typename parent_type::mutex_type mutex_type;
00190 typedef typename parent_type::volatile_reference_type volatile_reference_type;
00191
00192 public:
00196 readlock_acquirer(volatile_reference_type _a_value, mutex_type& _a_mutex):
00197 parent_type(_a_value, _a_mutex)
00198 {}
00203 template<typename T_lockfwd_arg1>
00204 readlock_acquirer(volatile_reference_type _a_value, mutex_type& _a_mutex, T_lockfwd_arg1 lockfwd_arg1):
00205 parent_type(_a_value, _a_mutex, lockfwd_arg1)
00206 {}
00207 };
00208
00241 template<locking_policy I_policy, typename T_type, typename T_mutex>
00242 class lock_acquirer<I_policy, T_type, T_mutex, std::tr1::true_type>:
00243
00244 public lock_acquirer<
00245 I_policy,
00246
00247 typename boost::mpl::eval_if<
00248 std::tr1::is_const<T_type>,
00249
00250 std::tr1::add_const<typename T_type::acquired_type>,
00251
00252 boost::mpl::identity<typename T_type::acquired_type>
00253 >::type,
00254 T_mutex
00255
00256
00257 >
00258 {
00259 typedef lock_acquirer<
00260 I_policy,
00261 typename boost::mpl::eval_if<
00262 std::tr1::is_const<T_type>,
00263 std::tr1::add_const<typename T_type::acquired_type>,
00264 boost::mpl::identity<typename T_type::acquired_type>
00265 >::type,
00266 T_mutex
00267
00268 > parent_type;
00269 typedef T_type lockable_type;
00270
00271
00272 public:
00276 explicit lock_acquirer(lockable_type& _a_lockable):
00277 parent_type(_a_lockable.access_volatile(), _a_lockable.mutex())
00278 {}
00283 template<typename T_lockfwd_arg1>
00284 lock_acquirer(lockable_type& _a_lockable, T_lockfwd_arg1 lockfwd_arg1):
00285 parent_type(_a_lockable.access_volatile(), _a_lockable.mutex(), lockfwd_arg1)
00286 {}
00287 };
00288
00289
00292 template<typename T_type, typename T_mutex>
00293 class writelock_acquirer<T_type, T_mutex, std::tr1::true_type>: public lock_acquirer<writelock, T_type, T_mutex, std::tr1::true_type>
00294 {
00295 typedef lock_acquirer<writelock, T_type, T_mutex, std::tr1::true_type> parent_type;
00296 typedef T_type lockable_type;
00297
00298
00299 public:
00303 explicit writelock_acquirer(lockable_type& _a_lockable):
00304 parent_type(_a_lockable)
00305 {}
00310 template<typename T_lockfwd_arg1>
00311 writelock_acquirer(lockable_type& _a_lockable, T_lockfwd_arg1 lockfwd_arg1):
00312 parent_type(_a_lockable, lockfwd_arg1)
00313 {}
00314 };
00315
00316
00319 template<typename T_type, typename T_mutex>
00320 class readlock_acquirer<T_type, T_mutex, std::tr1::true_type>: public lock_acquirer<readlock, T_type, T_mutex, std::tr1::true_type>
00321 {
00322 typedef lock_acquirer<readlock, T_type, T_mutex, std::tr1::true_type> parent_type;
00323 typedef T_type lockable_type;
00324
00325
00326 public:
00330 explicit readlock_acquirer(lockable_type& _a_lockable):
00331 parent_type(_a_lockable)
00332 {}
00337 template<typename T_lockfwd_arg1>
00338 readlock_acquirer(lockable_type& _a_lockable, T_lockfwd_arg1 lockfwd_arg1):
00339 parent_type(_a_lockable, lockfwd_arg1)
00340 {}
00341 };
00342
00343
00344
00348 }
00349
00350
00351 #endif // end file guard