/usr/include/sigx-2.0/sigx/lock_acquirer.h is in libsigx-2.0-dev 2.0.2-3.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 | #ifndef _SIGX_LOCK_ACQUIRER_H_
#define _SIGX_LOCK_ACQUIRER_H_
/*
* Copyright 2006 Klaus Triendl
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Inspired by Andrei Alexandrescu's article "volatile - Multithreaded
* Programmer's Best Friend":
* http://www.ddj.com/dept/cpp/184403766
*/
#include <tr1/type_traits>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/identity.hpp>
#include <sigx/noncopyable.h>
//#include <sigx/nonheapallocatable.h>
#include <sigx/nonpointeraliasing.h>
#include <sigx/lockable_fwddecl.h>
#include <sigx/choose_lock.h>
namespace sigx
{
/** @addtogroup threadsafety
* @{
*/
/** @short Locks the given mutex and ensures threadsafe write
* access to the given locked type.
*
* Collects acquisition of a mutex lock and a volatile_cast from a
* volatile object.
* A lock_acquirer object is initialized with a lock from an associated mutex
* and a volatile object.
* The appropriate lock is chosen by the metafunction choose_lock according to the
* mutex and the locking policy (read/write). Note that because the lock_acquirer is
* scope bound choose_lock must only choose scoped lock types.
*
* During its lifetime, a lock_acquirer keeps the lock acquired. Also, lock_acquirer
* offers read or write access (according to the locking policy) to the volatile-stripped object.
* Access is granted by a protected friend template function access_acquiree().
* The volatile_cast is performed by access_acquiree().
* The cast is semantically valid because lock_acquirer keeps the lock acquired
* for its lifetime.
*
* If the locking policy is readlock then the lock_acquirer grants only const access to the
* protected variable.
*
* The following template arguments are used:
* - @e T_type The type to be protected by the lock, e.g. an int.
* - @e T_mutex The lock, e.g. a Glib::Mutex.
* - @e I_islockable Whether T_type derives from lockable_base
*
* @note The locked type can only be accessed with access_acquiree()
* @code
* // somewhere
* boost::mutex mtx;
* int x;
*
* // a scope somewhere else
* {
* lock_acquirer<writelock, int, boost::mutex> l(x, mtx);
* int& i = access_acquiree(l);
* i = 42;
* }
* @endcode
*/
template<locking_policy I_policy, typename T_type, typename T_mutex, typename T_islockable>
class lock_acquirer: noncopyable/*, nonheapallocatable*/, nonpointeraliasing
{
protected:
typedef T_type acquired_type;
typedef T_mutex mutex_type;
// value_type = acquired_type with top-level reference stripped off
typedef typename std::tr1::remove_reference<acquired_type>::type value_type;
// const_or_value_type = unchanged value_type if policy is writelock, const value_type if readlock
typedef typename boost::mpl::eval_if_c<
I_policy == readlock,
std::tr1::add_const<value_type>,
boost::mpl::identity<value_type>
>::type const_or_value_type;
typedef typename std::tr1::add_reference<typename std::tr1::add_volatile<value_type>::type>::type volatile_reference_type;
typedef typename std::tr1::add_reference<typename std::tr1::remove_volatile<const_or_value_type>::type>::type reference_type;
/** @short Gives non-volatile access to the locked type
*
* Forces the programmer to pass a previously named lock_acquirer object thus
* ensuring that the lock is active throughout the usage of the locked object.
*/
friend reference_type
access_acquiree(lock_acquirer& l) throw()
{
return l.access_acquiree();
}
public:
/** @short Constructs a lock_acquirer from a volatile type to protect and a lock.
* @note Acquires the lock immediately, unlocks when it goes out of scope.
* @attention We rely here on the fact that members are initialized according
* to the order in which they are declared in a class, such that
* the lock is acquired before _a_value is accessed non-volatile.
*/
lock_acquirer(volatile_reference_type _a_value, mutex_type& _a_mutex):
m_lock(_a_mutex),
// volatile_cast
m_acquiree(const_cast<reference_type>(_a_value))
{}
/** @short Constructs a lock_acquirer from a volatile type to protect, a lock and
* an additional argument forwarded to the lock constructor.
* @note Acquires the lock immediately, unlocks when it goes out of scope
*/
template<typename T_lockfwd_arg1>
lock_acquirer(volatile_reference_type _a_value, mutex_type& _a_mutex, T_lockfwd_arg1 lockfwd_arg1):
m_lock(_a_mutex, lockfwd_arg1),
// volatile_cast
m_acquiree(const_cast<reference_type>(_a_value))
{}
protected:
/** @return The locked type with the `volatile" qualifier removed
*/
reference_type access_acquiree() throw()
{
return m_acquiree;
}
protected:
/** @short lock manager appropriate for the lock type
*/
typename choose_lock<mutex_type, I_policy>::type m_lock;
/** @short non-const reference to the locked object
*/
reference_type m_acquiree;
};
template<typename T_type, typename T_mutex, typename T_islockable>
class writelock_acquirer: public lock_acquirer<writelock, T_type, T_mutex, T_islockable>
{
typedef lock_acquirer<writelock, T_type, T_mutex, T_islockable> parent_type;
typedef typename parent_type::mutex_type mutex_type;
typedef typename parent_type::volatile_reference_type volatile_reference_type;
public:
/** @short Constructs a lock_acquirer from a volatile type to lock and a lock.
* @note Acquires the lock immediately, unlocks when it goes out of scope
*/
writelock_acquirer(volatile_reference_type _a_value, mutex_type& _a_mutex):
parent_type(_a_value, _a_mutex)
{}
/** @short Constructs a lock_acquirer from a volatile type to protect, a lock and
* an additional argument forwarded to the lock constructor.
* @note Acquires the lock immediately, unlocks when it goes out of scope
*/
template<typename T_lockfwd_arg1>
writelock_acquirer(volatile_reference_type _a_value, mutex_type& _a_mutex, T_lockfwd_arg1 lockfwd_arg1):
parent_type(_a_value, _a_mutex, lockfwd_arg1)
{}
};
template<typename T_type, typename T_mutex, typename T_islockable>
class readlock_acquirer: public lock_acquirer<readlock, T_type, T_mutex, T_islockable>
{
typedef lock_acquirer<readlock, T_type, T_mutex, T_islockable> parent_type;
typedef typename parent_type::mutex_type mutex_type;
typedef typename parent_type::volatile_reference_type volatile_reference_type;
public:
/** @short Constructs a lock_acquirer from a volatile type to lock and a lock.
* @note Acquires the lock immediately, unlocks when it goes out of scope
*/
readlock_acquirer(volatile_reference_type _a_value, mutex_type& _a_mutex):
parent_type(_a_value, _a_mutex)
{}
/** @short Constructs a lock_acquirer from a volatile type to protect, a lock and
* an additional argument forwarded to the lock constructor.
* @note Acquires the lock immediately, unlocks when it goes out of scope
*/
template<typename T_lockfwd_arg1>
readlock_acquirer(volatile_reference_type _a_value, mutex_type& _a_mutex, T_lockfwd_arg1 lockfwd_arg1):
parent_type(_a_value, _a_mutex, lockfwd_arg1)
{}
};
/** @short Specialization for a lockable_base derived object; locks the given
* lockable object (e.g. a mutex_lockable) and ensures
* threadsafe write access to the locked type.
*
* Collects acquisition of a mutex lock and a volatile_cast from the volatile
* object contained in the lockable.
* A lock_acquirer object is initialized with a lockable object.
* During its lifetime, a lock_acquirer keeps the lock acquired. Also, lock_acquirer
* offers write access to the volatile-stripped object. The access is offered
* with a related access_acquiree() function. The volatile_cast is performed by access_acquiree().
* The cast is semantically valid because lock_acquirer keeps the lock acquired
* for its lifetime.
*
* The following template arguments are used:
* - @e T_lockable A lockable_base derived type, e.g. a mutex_lockable<int>.
*
* The lock_acquirer chooses the appropriate lock manager for the lock automatically
* by applying the choose_lock.
*
* @note The locked type can only be accessed with access_acquiree()
* @code
* // somewhere
* mutex_lockable<int> lockable_int;
*
* // a scope somewhere else
* {
* lock_acquirer<writelock, mutex_lockable<int> > l(lockable_int);
* int& i = access_acquiree(l);
* i = 42;
* }
* @endcode
*/
template<locking_policy I_policy, typename T_type, typename T_mutex>
class lock_acquirer<I_policy, T_type, T_mutex, std::tr1::true_type>:
// derive from lock_acquirer for the locked type (which is lockable::acquired_type);
public lock_acquirer<
I_policy,
// if the lockable is const ...
typename boost::mpl::eval_if<
std::tr1::is_const<T_type>,
// ... then transfer constness to the type to protect (constness for lockables and the locked type is transitive)
std::tr1::add_const<typename T_type::acquired_type>,
// ... otherwise keep it as specified
boost::mpl::identity<typename T_type::acquired_type>
>::type,
T_mutex
// let compiler deduce whether acquired_type is again a lockable
/*, std::tr1::false_type*/
>
{
typedef lock_acquirer<
I_policy,
typename boost::mpl::eval_if<
std::tr1::is_const<T_type>,
std::tr1::add_const<typename T_type::acquired_type>,
boost::mpl::identity<typename T_type::acquired_type>
>::type,
T_mutex
/*, std::tr1::false_type*/
> parent_type;
typedef T_type lockable_type;
public:
/** @short Constructs a lock_acquirer from a lockable.
* @note Acquires the lock immediately, unlocks when it goes out of scope
*/
explicit lock_acquirer(lockable_type& _a_lockable):
parent_type(_a_lockable.access_volatile(), _a_lockable.mutex())
{}
/** @short Constructs a lock_acquirer from a volatile type to protect, a lock and
* an additional argument forwarded to the lock constructor.
* @note Acquires the lock immediately, unlocks when it goes out of scope
*/
template<typename T_lockfwd_arg1>
lock_acquirer(lockable_type& _a_lockable, T_lockfwd_arg1 lockfwd_arg1):
parent_type(_a_lockable.access_volatile(), _a_lockable.mutex(), lockfwd_arg1)
{}
};
/** @short writelock_acquirer specialization for lockable's.
*/
template<typename T_type, typename T_mutex>
class writelock_acquirer<T_type, T_mutex, std::tr1::true_type>: public lock_acquirer<writelock, T_type, T_mutex, std::tr1::true_type>
{
typedef lock_acquirer<writelock, T_type, T_mutex, std::tr1::true_type> parent_type;
typedef T_type lockable_type;
public:
/** @short Constructs a lock_acquirer from a lockable.
* @note Acquires the lock immediately, unlocks when it goes out of scope
*/
explicit writelock_acquirer(lockable_type& _a_lockable):
parent_type(_a_lockable)
{}
/** @short Constructs a lock_acquirer from a volatile type to protect, a lock and
* an additional argument forwarded to the lock constructor.
* @note Acquires the lock immediately, unlocks when it goes out of scope
*/
template<typename T_lockfwd_arg1>
writelock_acquirer(lockable_type& _a_lockable, T_lockfwd_arg1 lockfwd_arg1):
parent_type(_a_lockable, lockfwd_arg1)
{}
};
/** @short readlock_acquirer specialization for lockable's.
*/
template<typename T_type, typename T_mutex>
class readlock_acquirer<T_type, T_mutex, std::tr1::true_type>: public lock_acquirer<readlock, T_type, T_mutex, std::tr1::true_type>
{
typedef lock_acquirer<readlock, T_type, T_mutex, std::tr1::true_type> parent_type;
typedef T_type lockable_type;
public:
/** @short Constructs a lock_acquirer from a lockable.
* @note Acquires the lock immediately, unlocks when it goes out of scope
*/
explicit readlock_acquirer(lockable_type& _a_lockable):
parent_type(_a_lockable)
{}
/** @short Constructs a lock_acquirer from a volatile type to protect, a lock and
* an additional argument forwarded to the lock constructor.
* @note Acquires the lock immediately, unlocks when it goes out of scope
*/
template<typename T_lockfwd_arg1>
readlock_acquirer(lockable_type& _a_lockable, T_lockfwd_arg1 lockfwd_arg1):
parent_type(_a_lockable, lockfwd_arg1)
{}
};
// @addtogroup threadsafety
/** @}
*/
} // namespace mbox
#endif // end file guard
|