lockable.h

Go to the documentation of this file.
00001 #ifndef _SIGX_LOCKABLE_H_
00002 #define _SIGX_LOCKABLE_H_
00003 
00004 /*
00005  * Copyright 2008 Klaus Triendl
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Library General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00015  * Library General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Library General Public
00018  * License along with this library; if not, write to the Free 
00019  * Software Foundation, 51 Franklin Street, Fifth Floor, 
00020  * Boston, MA 02110-1301, USA.
00021 */
00022 
00023 /*
00024  * Inspired by Andrei Alexandrescu's article "volatile - Multithreaded 
00025  * Programmer's Best Friend":
00026  * http://www.ddj.com/dept/cpp/184403766
00027 */
00028 
00029 #include <tr1/type_traits>
00030 #include <sigx/noncopyable.h>
00031 #include <sigx/lockable_fwddecl.h>
00032 #include <sigx/const_trait.h>
00033 #include <sigx/volatile_trait.h>
00034 
00035 
00036 namespace sigx
00037 {
00038 
00050 template<typename T_mutex>
00051 struct lockable_base: noncopyable
00052 {
00053     typedef T_mutex mutex_type;
00054 
00055 
00056     mutex_type& mutex() const throw()
00057     {
00058         return m_mutex;
00059     }
00060 
00061 protected:
00062     lockable_base(): 
00063         m_mutex()
00064     {}
00065 
00066 
00069     mutable mutex_type m_mutex;
00070 };
00071 
00072 
00073 
00090 template<typename T_type, typename T_mutex>
00091 struct safe_lockable: public lockable_base<T_mutex>
00092 {
00093     // lock_acquirer can use interface methods
00094     template<locking_policy I_policy, typename T_type1, typename T_mutex1, typename T_islockable> friend class lock_acquirer;
00095 
00096     typedef lockable_base<T_mutex> parent_type;
00097     // acquired_type = type to protect, 1:1 from T_type
00098     typedef T_type acquired_type;
00099     // volatile_type = make T_type volatile, even if T_type is a reference
00100     // volatile T_type or volatile T_type&
00101     typedef typename volatile_trait<acquired_type>::add volatile_type;
00102     // reference_type = reference to volatile-stripped T_type
00103     // T_type&
00104     typedef typename std::tr1::add_reference<typename volatile_trait<acquired_type>::remove>::type reference_type;
00105     // volatile_reference_type = reference to volatile T_type, even if T_type is a reference
00106     // volatile T_type&
00107     typedef typename std::tr1::add_reference<volatile_type>::type volatile_reference_type;
00108     // reference_type = reference to volatile-stripped T_type, even if T_type is a reference
00109     // const T_type&
00110     typedef typename std::tr1::add_reference<typename const_trait<reference_type>::add>::type const_reference_type;
00111     // cv_reference_type = reference to cv-qualified T_type, even if T_type is a reference
00112     // const volatile T_type&
00113     typedef typename std::tr1::add_reference<typename const_trait<volatile_type>::add>::type cv_reference_type;
00114     // apply const qualifier and reference to toplevel type, unchanged if toplevel type is a reference
00115     typedef typename std::tr1::add_reference<typename std::tr1::add_const<acquired_type>::type>::type toplevel_const_reference_type;
00116 
00117 
00122     safe_lockable(): 
00123         parent_type(), 
00124         m_obj()
00125     {}
00126     
00129     safe_lockable(toplevel_const_reference_type _a_value): 
00130         parent_type(), 
00131         m_obj(_a_value)
00132     {}
00133 
00134 
00135 protected:
00138     volatile_reference_type access_volatile() throw()
00139     {
00140         return m_obj;
00141     }
00142 
00145     reference_type access_nonvolatile() throw()
00146     {
00147         // volatile_cast m_obj
00148         return const_cast<reference_type>(m_obj);
00149     }
00150 
00153     cv_reference_type access_volatile() const throw()
00154     {
00155         return m_obj;
00156     }
00157 
00160     const_reference_type access_nonvolatile() const throw()
00161     {
00162         // volatile_cast m_obj
00163         return const_cast<const_reference_type>(m_obj);
00164     }
00165 
00166     
00167 private:
00170     volatile_type m_obj;
00171 };
00172 
00173 
00176 template<typename T_type, typename T_mutex>
00177 struct lockable: public safe_lockable<T_type, T_mutex>
00178 {
00179     typedef safe_lockable<T_type, T_mutex> parent_type;
00180     typedef typename parent_type::toplevel_const_reference_type toplevel_const_reference_type;
00181 
00182 public:
00187     lockable(): 
00188         parent_type()
00189     {}
00190     
00193     lockable(toplevel_const_reference_type _a_value): 
00194         parent_type(_a_value)
00195     {}
00196 
00197     // make safe_lockable's interface publicly available
00198     using parent_type::access_volatile;
00199     using parent_type::access_nonvolatile;
00200 };
00201 
00202 
00203 
00204 #if 0 // specializations for pointers
00205 
00214 template<typename T_mutex>
00215 struct lockable<void*, T_mutex>: public lockable_base<T_mutex>
00216 {
00217     typedef void* acquired_type;
00218     typedef T_mutex mutex_type;
00219     typedef lockable_base<mutex_type> parent_type;
00220     typedef lockable<acquired_type, mutex_type> type;
00221     typedef typename volatile_trait<acquired_type>::add volatile_type; 
00222     typedef typename std::tr1::add_reference<typename volatile_trait<acquired_type>::remove>::type reference_type;
00223     typedef typename std::tr1::add_reference<typename volatile_trait<acquired_type>::add>::type volatile_reference_type;
00224     typedef typename std::tr1::add_reference<typename std::tr1::add_const<acquired_type>::type>::type take_type;
00225 
00226     
00231     lockable(take_type _a_value = 0): 
00232         parent_type(), 
00233         m_obj(_a_value)
00234     {}
00235 
00238     volatile_reference_type access_volatile()
00239     {
00240         return m_obj;
00241     }
00242 
00245     reference_type access_nonvolatile()
00246     {
00247         // volatile_cast m_obj
00248         return const_cast<reference_type>(m_obj);
00249     }
00250 
00251     
00252 private:
00255     volatile_type m_obj;
00256 };
00257 
00258 
00259 
00270 template<typename T_type, typename T_mutex>
00271 struct lockable<T_type*, T_mutex>: public lockable<void*, T_mutex>
00272 {
00273     typedef lockable<void*, T_mutex> parent_type;
00274     typedef T_type* acquired_type;
00275     typedef lockable<acquired_type, mutex_type> type;
00276     typedef typename volatile_trait<acquired_type>::add volatile_type; 
00277     typedef typename std::tr1::add_reference<typename volatile_trait<acquired_type>::remove>::type reference_type;
00278     typedef typename std::tr1::add_reference<typename volatile_trait<acquired_type>::add>::type volatile_reference_type;
00279     typedef typename std::tr1::add_reference<typename std::tr1::add_const<acquired_type>::type>::type take_type;
00280 
00281     
00286     lockable(take_type _a_value = 0): 
00287         parent_type((void*&) _a_value)
00288     {}
00289 
00295     volatile_reference_type access_volatile()
00296     {
00297         return (volatile_reference_type) parent_type::access_volatile();
00298     }
00299 
00302     reference_type access_acquiree()
00303     {
00304         return (reference_type) parent_type::access_acquiree();
00305     }
00306 };
00307 #endif
00308 
00309 
00310 
00311 // @addtogroup threadsafety
00315 } // namespace sigx
00316 
00317 
00318 #endif // end file guard

Generated on Wed Jan 28 21:37:59 2009 for sigx++ by  doxygen 1.5.8