annotate DEPENDENCIES/generic/include/boost/thread/synchronized_value.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 // (C) Copyright 2010 Just Software Solutions Ltd http://www.justsoftwaresolutions.co.uk
Chris@16 2 // (C) Copyright 2012 Vicente J. Botet Escriba
Chris@16 3 // Distributed under the Boost Software License, Version 1.0. (See
Chris@16 4 // accompanying file LICENSE_1_0.txt or copy at
Chris@16 5 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 6
Chris@16 7
Chris@16 8 #ifndef BOOST_THREAD_SYNCHRONIZED_VALUE_HPP
Chris@16 9 #define BOOST_THREAD_SYNCHRONIZED_VALUE_HPP
Chris@16 10
Chris@16 11 #include <boost/thread/detail/config.hpp>
Chris@16 12
Chris@16 13 #include <boost/thread/detail/move.hpp>
Chris@16 14 #include <boost/thread/mutex.hpp>
Chris@16 15 #include <boost/thread/lock_types.hpp>
Chris@16 16 #include <boost/thread/lock_guard.hpp>
Chris@16 17 #include <boost/thread/lock_algorithms.hpp>
Chris@16 18 #include <boost/thread/lock_factories.hpp>
Chris@16 19 #include <boost/thread/strict_lock.hpp>
Chris@101 20 #include <boost/core/swap.hpp>
Chris@16 21 #include <boost/utility/declval.hpp>
Chris@16 22 //#include <boost/type_traits.hpp>
Chris@16 23 //#include <boost/thread/detail/is_nothrow_default_constructible.hpp>
Chris@16 24 //#if ! defined BOOST_NO_CXX11_HDR_TYPE_TRAITS
Chris@16 25 //#include <type_traits>
Chris@16 26 //#endif
Chris@16 27
Chris@16 28 #if ! defined(BOOST_THREAD_NO_SYNCHRONIZE)
Chris@16 29 #include <tuple> // todo change to <boost/tuple.hpp> once Boost.Tuple or Boost.Fusion provides Move semantics on C++98 compilers.
Chris@16 30 #include <functional>
Chris@16 31 #endif
Chris@16 32
Chris@16 33 #include <boost/utility/result_of.hpp>
Chris@16 34
Chris@16 35 #include <boost/config/abi_prefix.hpp>
Chris@16 36
Chris@16 37 namespace boost
Chris@16 38 {
Chris@16 39
Chris@16 40 /**
Chris@16 41 * strict lock providing a const pointer access to the synchronized value type.
Chris@16 42 *
Chris@16 43 * @param T the value type.
Chris@16 44 * @param Lockable the mutex type protecting the value type.
Chris@16 45 */
Chris@16 46 template <typename T, typename Lockable = mutex>
Chris@16 47 class const_strict_lock_ptr
Chris@16 48 {
Chris@16 49 public:
Chris@16 50 typedef T value_type;
Chris@16 51 typedef Lockable mutex_type;
Chris@16 52 protected:
Chris@16 53
Chris@16 54 // this should be a strict_lock, but unique_lock is needed to be able to return it.
Chris@16 55 boost::unique_lock<mutex_type> lk_;
Chris@16 56 T const& value_;
Chris@16 57
Chris@16 58 public:
Chris@16 59 BOOST_THREAD_MOVABLE_ONLY( const_strict_lock_ptr )
Chris@16 60
Chris@16 61 /**
Chris@16 62 * @param value constant reference of the value to protect.
Chris@16 63 * @param mtx reference to the mutex used to protect the value.
Chris@16 64 * @effects locks the mutex @c mtx, stores a reference to it and to the value type @c value.
Chris@16 65 */
Chris@16 66 const_strict_lock_ptr(T const& val, Lockable & mtx) :
Chris@16 67 lk_(mtx), value_(val)
Chris@16 68 {
Chris@16 69 }
Chris@16 70 const_strict_lock_ptr(T const& val, Lockable & mtx, adopt_lock_t tag) BOOST_NOEXCEPT :
Chris@16 71 lk_(mtx, tag), value_(val)
Chris@16 72 {
Chris@16 73 }
Chris@16 74 /**
Chris@16 75 * Move constructor.
Chris@16 76 * @effects takes ownership of the mutex owned by @c other, stores a reference to the mutex and the value type of @c other.
Chris@16 77 */
Chris@16 78 const_strict_lock_ptr(BOOST_THREAD_RV_REF(const_strict_lock_ptr) other) BOOST_NOEXCEPT
Chris@16 79 : lk_(boost::move(BOOST_THREAD_RV(other).lk_)),value_(BOOST_THREAD_RV(other).value_)
Chris@16 80 {
Chris@16 81 }
Chris@16 82
Chris@16 83 ~const_strict_lock_ptr()
Chris@16 84 {
Chris@16 85 }
Chris@16 86
Chris@16 87 /**
Chris@16 88 * @return a constant pointer to the protected value
Chris@16 89 */
Chris@16 90 const T* operator->() const
Chris@16 91 {
Chris@16 92 return &value_;
Chris@16 93 }
Chris@16 94
Chris@16 95 /**
Chris@16 96 * @return a constant reference to the protected value
Chris@16 97 */
Chris@16 98 const T& operator*() const
Chris@16 99 {
Chris@16 100 return value_;
Chris@16 101 }
Chris@16 102
Chris@16 103 };
Chris@16 104
Chris@16 105 /**
Chris@16 106 * strict lock providing a pointer access to the synchronized value type.
Chris@16 107 *
Chris@16 108 * @param T the value type.
Chris@16 109 * @param Lockable the mutex type protecting the value type.
Chris@16 110 */
Chris@16 111 template <typename T, typename Lockable = mutex>
Chris@16 112 class strict_lock_ptr : public const_strict_lock_ptr<T,Lockable>
Chris@16 113 {
Chris@16 114 typedef const_strict_lock_ptr<T,Lockable> base_type;
Chris@16 115 public:
Chris@16 116 BOOST_THREAD_MOVABLE_ONLY( strict_lock_ptr )
Chris@16 117
Chris@16 118 /**
Chris@16 119 * @param value reference of the value to protect.
Chris@16 120 * @param mtx reference to the mutex used to protect the value.
Chris@16 121 * @effects locks the mutex @c mtx, stores a reference to it and to the value type @c value.
Chris@16 122 */
Chris@16 123 strict_lock_ptr(T & val, Lockable & mtx) :
Chris@16 124 base_type(val, mtx)
Chris@16 125 {
Chris@16 126 }
Chris@16 127 strict_lock_ptr(T & val, Lockable & mtx, adopt_lock_t tag) :
Chris@16 128 base_type(val, mtx, tag)
Chris@16 129 {
Chris@16 130 }
Chris@16 131
Chris@16 132 /**
Chris@16 133 * Move constructor.
Chris@16 134 * @effects takes ownership of the mutex owned by @c other, stores a reference to the mutex and the value type of @c other.
Chris@16 135 */
Chris@16 136 strict_lock_ptr(BOOST_THREAD_RV_REF(strict_lock_ptr) other)
Chris@16 137 : base_type(boost::move(static_cast<base_type&>(other)))
Chris@16 138 {
Chris@16 139 }
Chris@16 140
Chris@16 141 ~strict_lock_ptr()
Chris@16 142 {
Chris@16 143 }
Chris@16 144
Chris@16 145 /**
Chris@16 146 * @return a pointer to the protected value
Chris@16 147 */
Chris@16 148 T* operator->()
Chris@16 149 {
Chris@16 150 return const_cast<T*>(&this->value_);
Chris@16 151 }
Chris@16 152
Chris@16 153 /**
Chris@16 154 * @return a reference to the protected value
Chris@16 155 */
Chris@16 156 T& operator*()
Chris@16 157 {
Chris@16 158 return const_cast<T&>(this->value_);
Chris@16 159 }
Chris@16 160
Chris@16 161 };
Chris@16 162
Chris@16 163 template <typename SV>
Chris@16 164 struct synchronized_value_strict_lock_ptr
Chris@16 165 {
Chris@16 166 typedef strict_lock_ptr<typename SV::value_type, typename SV::mutex_type> type;
Chris@16 167 };
Chris@16 168
Chris@16 169 template <typename SV>
Chris@16 170 struct synchronized_value_strict_lock_ptr<const SV>
Chris@16 171 {
Chris@16 172 typedef const_strict_lock_ptr<typename SV::value_type, typename SV::mutex_type> type;
Chris@16 173 };
Chris@16 174 /**
Chris@16 175 * unique_lock providing a const pointer access to the synchronized value type.
Chris@16 176 *
Chris@16 177 * An object of type const_unique_lock_ptr is a unique_lock that provides a const pointer access to the synchronized value type.
Chris@16 178 * As unique_lock controls the ownership of a lockable object within a scope.
Chris@16 179 * Ownership of the lockable object may be acquired at construction or after construction,
Chris@16 180 * and may be transferred, after acquisition, to another const_unique_lock_ptr object.
Chris@16 181 * Objects of type const_unique_lock_ptr are not copyable but are movable.
Chris@16 182 * The behavior of a program is undefined if the mutex and the value type
Chris@16 183 * pointed do not exist for the entire remaining lifetime of the const_unique_lock_ptr object.
Chris@16 184 * The supplied Mutex type shall meet the BasicLockable requirements.
Chris@16 185 *
Chris@16 186 * @note const_unique_lock_ptr<T, Lockable> meets the Lockable requirements.
Chris@16 187 * If Lockable meets the TimedLockable requirements, const_unique_lock_ptr<T,Lockable>
Chris@16 188 * also meets the TimedLockable requirements.
Chris@16 189 *
Chris@16 190 * @param T the value type.
Chris@16 191 * @param Lockable the mutex type protecting the value type.
Chris@16 192 */
Chris@16 193 template <typename T, typename Lockable = mutex>
Chris@16 194 class const_unique_lock_ptr : public unique_lock<Lockable>
Chris@16 195 {
Chris@16 196 typedef unique_lock<Lockable> base_type;
Chris@16 197 public:
Chris@16 198 typedef T value_type;
Chris@16 199 typedef Lockable mutex_type;
Chris@16 200 protected:
Chris@16 201 T const& value_;
Chris@16 202
Chris@16 203 public:
Chris@16 204 BOOST_THREAD_MOVABLE_ONLY(const_unique_lock_ptr)
Chris@16 205
Chris@16 206 /**
Chris@16 207 * @param value reference of the value to protect.
Chris@16 208 * @param mtx reference to the mutex used to protect the value.
Chris@16 209 *
Chris@16 210 * @requires If mutex_type is not a recursive mutex the calling thread does not own the mutex.
Chris@16 211 *
Chris@16 212 * @effects locks the mutex @c mtx, stores a reference to it and to the value type @c value.
Chris@16 213 */
Chris@16 214 const_unique_lock_ptr(T const& val, Lockable & mtx)
Chris@16 215 : base_type(mtx), value_(val)
Chris@16 216 {
Chris@16 217 }
Chris@16 218 /**
Chris@16 219 * @param value reference of the value to protect.
Chris@16 220 * @param mtx reference to the mutex used to protect the value.
Chris@16 221 * @param tag of type adopt_lock_t used to differentiate the constructor.
Chris@16 222 * @requires The calling thread own the mutex.
Chris@16 223 * @effects stores a reference to it and to the value type @c value taking ownership.
Chris@16 224 */
Chris@16 225 const_unique_lock_ptr(T const& val, Lockable & mtx, adopt_lock_t) BOOST_NOEXCEPT
Chris@16 226 : base_type(mtx, adopt_lock), value_(val)
Chris@16 227 {
Chris@16 228 }
Chris@16 229 /**
Chris@16 230 * @param value reference of the value to protect.
Chris@16 231 * @param mtx reference to the mutex used to protect the value.
Chris@16 232 * @param tag of type defer_lock_t used to differentiate the constructor.
Chris@16 233 * @effects stores a reference to it and to the value type @c value c.
Chris@16 234 */
Chris@16 235 const_unique_lock_ptr(T const& val, Lockable & mtx, defer_lock_t) BOOST_NOEXCEPT
Chris@16 236 : base_type(mtx, defer_lock), value_(val)
Chris@16 237 {
Chris@16 238 }
Chris@16 239 /**
Chris@16 240 * @param value reference of the value to protect.
Chris@16 241 * @param mtx reference to the mutex used to protect the value.
Chris@16 242 * @param tag of type try_to_lock_t used to differentiate the constructor.
Chris@16 243 * @requires If mutex_type is not a recursive mutex the calling thread does not own the mutex.
Chris@16 244 * @effects try to lock the mutex @c mtx, stores a reference to it and to the value type @c value.
Chris@16 245 */
Chris@16 246 const_unique_lock_ptr(T const& val, Lockable & mtx, try_to_lock_t) BOOST_NOEXCEPT
Chris@16 247 : base_type(mtx, try_to_lock), value_(val)
Chris@16 248 {
Chris@16 249 }
Chris@16 250 /**
Chris@16 251 * Move constructor.
Chris@16 252 * @effects takes ownership of the mutex owned by @c other, stores a reference to the mutex and the value type of @c other.
Chris@16 253 */
Chris@16 254 const_unique_lock_ptr(BOOST_THREAD_RV_REF(const_unique_lock_ptr) other) BOOST_NOEXCEPT
Chris@16 255 : base_type(boost::move(static_cast<base_type&>(other))), value_(BOOST_THREAD_RV(other).value_)
Chris@16 256 {
Chris@16 257 }
Chris@16 258
Chris@16 259 /**
Chris@16 260 * @effects If owns calls unlock() on the owned mutex.
Chris@16 261 */
Chris@16 262 ~const_unique_lock_ptr()
Chris@16 263 {
Chris@16 264 }
Chris@16 265
Chris@16 266 /**
Chris@16 267 * @return a constant pointer to the protected value
Chris@16 268 */
Chris@16 269 const T* operator->() const
Chris@16 270 {
Chris@16 271 BOOST_ASSERT (this->owns_lock());
Chris@16 272 return &value_;
Chris@16 273 }
Chris@16 274
Chris@16 275 /**
Chris@16 276 * @return a constant reference to the protected value
Chris@16 277 */
Chris@16 278 const T& operator*() const
Chris@16 279 {
Chris@16 280 BOOST_ASSERT (this->owns_lock());
Chris@16 281 return value_;
Chris@16 282 }
Chris@16 283
Chris@16 284 };
Chris@16 285
Chris@16 286 /**
Chris@16 287 * unique lock providing a pointer access to the synchronized value type.
Chris@16 288 *
Chris@16 289 * @param T the value type.
Chris@16 290 * @param Lockable the mutex type protecting the value type.
Chris@16 291 */
Chris@16 292 template <typename T, typename Lockable = mutex>
Chris@16 293 class unique_lock_ptr : public const_unique_lock_ptr<T, Lockable>
Chris@16 294 {
Chris@16 295 typedef const_unique_lock_ptr<T, Lockable> base_type;
Chris@16 296 public:
Chris@16 297 typedef T value_type;
Chris@16 298 typedef Lockable mutex_type;
Chris@16 299
Chris@16 300 BOOST_THREAD_MOVABLE_ONLY(unique_lock_ptr)
Chris@16 301
Chris@16 302 /**
Chris@16 303 * @param value reference of the value to protect.
Chris@16 304 * @param mtx reference to the mutex used to protect the value.
Chris@16 305 * @effects locks the mutex @c mtx, stores a reference to it and to the value type @c value.
Chris@16 306 */
Chris@16 307 unique_lock_ptr(T & val, Lockable & mtx)
Chris@16 308 : base_type(val, mtx)
Chris@16 309 {
Chris@16 310 }
Chris@16 311 /**
Chris@16 312 * @param value reference of the value to protect.
Chris@16 313 * @param mtx reference to the mutex used to protect the value.
Chris@16 314 * @param tag of type adopt_lock_t used to differentiate the constructor.
Chris@16 315 * @effects stores a reference to it and to the value type @c value taking ownership.
Chris@16 316 */
Chris@16 317 unique_lock_ptr(T & value, Lockable & mtx, adopt_lock_t) BOOST_NOEXCEPT
Chris@16 318 : base_type(value, mtx, adopt_lock)
Chris@16 319 {
Chris@16 320 }
Chris@16 321 /**
Chris@16 322 * @param value reference of the value to protect.
Chris@16 323 * @param mtx reference to the mutex used to protect the value.
Chris@16 324 * @param tag of type defer_lock_t used to differentiate the constructor.
Chris@16 325 * @effects stores a reference to it and to the value type @c value c.
Chris@16 326 */
Chris@16 327 unique_lock_ptr(T & value, Lockable & mtx, defer_lock_t) BOOST_NOEXCEPT
Chris@16 328 : base_type(value, mtx, defer_lock)
Chris@16 329 {
Chris@16 330 }
Chris@16 331 /**
Chris@16 332 * @param value reference of the value to protect.
Chris@16 333 * @param mtx reference to the mutex used to protect the value.
Chris@16 334 * @param tag of type try_to_lock_t used to differentiate the constructor.
Chris@16 335 * @effects try to lock the mutex @c mtx, stores a reference to it and to the value type @c value.
Chris@16 336 */
Chris@16 337 unique_lock_ptr(T & value, Lockable & mtx, try_to_lock_t) BOOST_NOEXCEPT
Chris@16 338 : base_type(value, mtx, try_to_lock)
Chris@16 339 {
Chris@16 340 }
Chris@16 341 /**
Chris@16 342 * Move constructor.
Chris@16 343 * @effects takes ownership of the mutex owned by @c other, stores a reference to the mutex and the value type of @c other.
Chris@16 344 */
Chris@16 345 unique_lock_ptr(BOOST_THREAD_RV_REF(unique_lock_ptr) other) BOOST_NOEXCEPT
Chris@16 346 : base_type(boost::move(static_cast<base_type&>(other)))
Chris@16 347 {
Chris@16 348 }
Chris@16 349
Chris@16 350 ~unique_lock_ptr()
Chris@16 351 {
Chris@16 352 }
Chris@16 353
Chris@16 354 /**
Chris@16 355 * @return a pointer to the protected value
Chris@16 356 */
Chris@16 357 T* operator->()
Chris@16 358 {
Chris@16 359 BOOST_ASSERT (this->owns_lock());
Chris@16 360 return const_cast<T*>(&this->value_);
Chris@16 361 }
Chris@16 362
Chris@16 363 /**
Chris@16 364 * @return a reference to the protected value
Chris@16 365 */
Chris@16 366 T& operator*()
Chris@16 367 {
Chris@16 368 BOOST_ASSERT (this->owns_lock());
Chris@16 369 return const_cast<T&>(this->value_);
Chris@16 370 }
Chris@16 371
Chris@16 372
Chris@16 373 };
Chris@16 374
Chris@16 375 template <typename SV>
Chris@16 376 struct synchronized_value_unique_lock_ptr
Chris@16 377 {
Chris@16 378 typedef unique_lock_ptr<typename SV::value_type, typename SV::mutex_type> type;
Chris@16 379 };
Chris@16 380
Chris@16 381 template <typename SV>
Chris@16 382 struct synchronized_value_unique_lock_ptr<const SV>
Chris@16 383 {
Chris@16 384 typedef const_unique_lock_ptr<typename SV::value_type, typename SV::mutex_type> type;
Chris@16 385 };
Chris@16 386 /**
Chris@16 387 * cloaks a value type and the mutex used to protect it together.
Chris@16 388 * @param T the value type.
Chris@16 389 * @param Lockable the mutex type protecting the value type.
Chris@16 390 */
Chris@16 391 template <typename T, typename Lockable = mutex>
Chris@16 392 class synchronized_value
Chris@16 393 {
Chris@16 394
Chris@16 395 #if ! defined(BOOST_THREAD_NO_MAKE_UNIQUE_LOCKS)
Chris@16 396 #if ! defined BOOST_NO_CXX11_VARIADIC_TEMPLATES
Chris@16 397 template <typename ...SV>
Chris@16 398 friend std::tuple<typename synchronized_value_strict_lock_ptr<SV>::type ...> synchronize(SV& ...sv);
Chris@16 399 #else
Chris@16 400 template <typename SV1, typename SV2>
Chris@16 401 friend std::tuple<
Chris@16 402 typename synchronized_value_strict_lock_ptr<SV1>::type,
Chris@16 403 typename synchronized_value_strict_lock_ptr<SV2>::type
Chris@16 404 >
Chris@16 405 synchronize(SV1& sv1, SV2& sv2);
Chris@16 406 template <typename SV1, typename SV2, typename SV3>
Chris@16 407 friend std::tuple<
Chris@16 408 typename synchronized_value_strict_lock_ptr<SV1>::type,
Chris@16 409 typename synchronized_value_strict_lock_ptr<SV2>::type,
Chris@16 410 typename synchronized_value_strict_lock_ptr<SV3>::type
Chris@16 411 >
Chris@16 412 synchronize(SV1& sv1, SV2& sv2, SV3& sv3);
Chris@16 413 #endif
Chris@16 414 #endif
Chris@16 415
Chris@16 416 public:
Chris@16 417 typedef T value_type;
Chris@16 418 typedef Lockable mutex_type;
Chris@16 419 private:
Chris@16 420 T value_;
Chris@16 421 mutable mutex_type mtx_;
Chris@16 422 public:
Chris@16 423 // construction/destruction
Chris@16 424 /**
Chris@16 425 * Default constructor.
Chris@16 426 *
Chris@16 427 * @Requires: T is DefaultConstructible
Chris@16 428 */
Chris@16 429 synchronized_value()
Chris@16 430 //BOOST_NOEXCEPT_IF(is_nothrow_default_constructible<T>::value)
Chris@16 431 : value_()
Chris@16 432 {
Chris@16 433 }
Chris@16 434
Chris@16 435 /**
Chris@16 436 * Constructor from copy constructible value.
Chris@16 437 *
Chris@16 438 * Requires: T is CopyConstructible
Chris@16 439 */
Chris@16 440 synchronized_value(T const& other)
Chris@16 441 //BOOST_NOEXCEPT_IF(is_nothrow_copy_constructible<T>::value)
Chris@16 442 : value_(other)
Chris@16 443 {
Chris@16 444 }
Chris@16 445
Chris@16 446 /**
Chris@16 447 * Move Constructor.
Chris@16 448 *
Chris@16 449 * Requires: T is CopyMovable
Chris@16 450 */
Chris@16 451 synchronized_value(BOOST_THREAD_RV_REF(T) other)
Chris@16 452 //BOOST_NOEXCEPT_IF(is_nothrow_move_constructible<T>::value)
Chris@16 453 : value_(boost::move(other))
Chris@16 454 {
Chris@16 455 }
Chris@16 456
Chris@16 457 /**
Chris@16 458 * Constructor from value type.
Chris@16 459 *
Chris@16 460 * Requires: T is DefaultConstructible and Assignable
Chris@16 461 * Effects: Assigns the value on a scope protected by the mutex of the rhs. The mutex is not copied.
Chris@16 462 */
Chris@16 463 synchronized_value(synchronized_value const& rhs)
Chris@16 464 {
Chris@16 465 strict_lock<mutex_type> lk(rhs.mtx_);
Chris@16 466 value_ = rhs.value_;
Chris@16 467 }
Chris@16 468
Chris@16 469 /**
Chris@16 470 * Move Constructor from movable value type
Chris@16 471 *
Chris@16 472 */
Chris@16 473 synchronized_value(BOOST_THREAD_RV_REF(synchronized_value) other)
Chris@16 474 {
Chris@101 475 strict_lock<mutex_type> lk(BOOST_THREAD_RV(other).mtx_);
Chris@101 476 value_= boost::move(BOOST_THREAD_RV(other).value_);
Chris@16 477 }
Chris@16 478
Chris@16 479 // mutation
Chris@16 480 /**
Chris@16 481 * Assignment operator.
Chris@16 482 *
Chris@16 483 * Effects: Copies the underlying value on a scope protected by the two mutexes.
Chris@16 484 * The mutex is not copied. The locks are acquired using lock, so deadlock is avoided.
Chris@16 485 * For example, there is no problem if one thread assigns a = b and the other assigns b = a.
Chris@16 486 *
Chris@16 487 * Return: *this
Chris@16 488 */
Chris@16 489
Chris@16 490 synchronized_value& operator=(synchronized_value const& rhs)
Chris@16 491 {
Chris@16 492 if(&rhs != this)
Chris@16 493 {
Chris@16 494 // auto _ = make_unique_locks(mtx_, rhs.mtx_);
Chris@16 495 unique_lock<mutex_type> lk1(mtx_, defer_lock);
Chris@16 496 unique_lock<mutex_type> lk2(rhs.mtx_, defer_lock);
Chris@16 497 lock(lk1,lk2);
Chris@16 498
Chris@16 499 value_ = rhs.value_;
Chris@16 500 }
Chris@16 501 return *this;
Chris@16 502 }
Chris@16 503 /**
Chris@16 504 * Assignment operator from a T const&.
Chris@16 505 * Effects: The operator copies the value on a scope protected by the mutex.
Chris@16 506 * Return: *this
Chris@16 507 */
Chris@16 508 synchronized_value& operator=(value_type const& val)
Chris@16 509 {
Chris@16 510 {
Chris@16 511 strict_lock<mutex_type> lk(mtx_);
Chris@16 512 value_ = val;
Chris@16 513 }
Chris@16 514 return *this;
Chris@16 515 }
Chris@16 516
Chris@16 517 //observers
Chris@16 518 /**
Chris@16 519 * Explicit conversion to value type.
Chris@16 520 *
Chris@16 521 * Requires: T is CopyConstructible
Chris@16 522 * Return: A copy of the protected value obtained on a scope protected by the mutex.
Chris@16 523 *
Chris@16 524 */
Chris@16 525 T get() const
Chris@16 526 {
Chris@16 527 strict_lock<mutex_type> lk(mtx_);
Chris@16 528 return value_;
Chris@16 529 }
Chris@16 530 /**
Chris@16 531 * Explicit conversion to value type.
Chris@16 532 *
Chris@16 533 * Requires: T is CopyConstructible
Chris@16 534 * Return: A copy of the protected value obtained on a scope protected by the mutex.
Chris@16 535 *
Chris@16 536 */
Chris@16 537 #if ! defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
Chris@16 538 explicit operator T() const
Chris@16 539 {
Chris@16 540 return get();
Chris@16 541 }
Chris@16 542 #endif
Chris@16 543
Chris@16 544 /**
Chris@16 545 * value type getter.
Chris@16 546 *
Chris@16 547 * Return: A constant reference to the protected value.
Chris@16 548 *
Chris@16 549 * Note: Not thread safe
Chris@16 550 *
Chris@16 551 */
Chris@16 552 T const& value() const
Chris@16 553 {
Chris@16 554 return value_;
Chris@16 555 }
Chris@16 556 /**
Chris@16 557 * mutex getter.
Chris@16 558 *
Chris@16 559 * Return: A constant reference to the protecting mutex.
Chris@16 560 *
Chris@16 561 * Note: Not thread safe
Chris@16 562 *
Chris@16 563 */
Chris@16 564 mutex_type const& mutex() const
Chris@16 565 {
Chris@16 566 return mtx_;
Chris@16 567 }
Chris@16 568 /**
Chris@16 569 * Swap
Chris@16 570 *
Chris@16 571 * Effects: Swaps the data. Again, locks are acquired using lock(). The mutexes are not swapped.
Chris@16 572 * A swap method accepts a T& and swaps the data inside a critical section.
Chris@16 573 * This is by far the preferred method of changing the guarded datum wholesale because it keeps the lock only
Chris@16 574 * for a short time, thus lowering the pressure on the mutex.
Chris@16 575 */
Chris@16 576 void swap(synchronized_value & rhs)
Chris@16 577 {
Chris@16 578 if (this == &rhs) {
Chris@16 579 return;
Chris@16 580 }
Chris@16 581 // auto _ = make_unique_locks(mtx_, rhs.mtx_);
Chris@16 582 unique_lock<mutex_type> lk1(mtx_, defer_lock);
Chris@16 583 unique_lock<mutex_type> lk2(rhs.mtx_, defer_lock);
Chris@16 584 lock(lk1,lk2);
Chris@16 585 boost::swap(value_, rhs.value_);
Chris@16 586 }
Chris@16 587 /**
Chris@16 588 * Swap with the underlying value type
Chris@16 589 *
Chris@16 590 * Effects: Swaps the data on a scope protected by the mutex.
Chris@16 591 */
Chris@16 592 void swap(value_type & rhs)
Chris@16 593 {
Chris@16 594 strict_lock<mutex_type> lk(mtx_);
Chris@16 595 boost::swap(value_, rhs);
Chris@16 596 }
Chris@16 597
Chris@16 598 /**
Chris@16 599 * Essentially calling a method obj->foo(x, y, z) calls the method foo(x, y, z) inside a critical section as
Chris@16 600 * long-lived as the call itself.
Chris@16 601 */
Chris@16 602 strict_lock_ptr<T,Lockable> operator->()
Chris@16 603 {
Chris@16 604 return BOOST_THREAD_MAKE_RV_REF((strict_lock_ptr<T,Lockable>(value_, mtx_)));
Chris@16 605 }
Chris@16 606 /**
Chris@16 607 * If the synchronized_value object involved is const-qualified, then you'll only be able to call const methods
Chris@16 608 * through operator->. So, for example, vec->push_back("xyz") won't work if vec were const-qualified.
Chris@16 609 * The locking mechanism capitalizes on the assumption that const methods don't modify their underlying data.
Chris@16 610 */
Chris@16 611 const_strict_lock_ptr<T,Lockable> operator->() const
Chris@16 612 {
Chris@16 613 return BOOST_THREAD_MAKE_RV_REF((const_strict_lock_ptr<T,Lockable>(value_, mtx_)));
Chris@16 614 }
Chris@16 615
Chris@16 616 /**
Chris@16 617 * Call function on a locked block.
Chris@16 618 *
Chris@16 619 * @requires fct(value_) is well formed.
Chris@16 620 *
Chris@16 621 * Example
Chris@16 622 * void fun(synchronized_value<vector<int>> & v) {
Chris@16 623 * v ( [](vector<int>> & vec)
Chris@16 624 * {
Chris@16 625 * vec.push_back(42);
Chris@16 626 * assert(vec.back() == 42);
Chris@16 627 * } );
Chris@16 628 * }
Chris@16 629 */
Chris@16 630 template <typename F>
Chris@16 631 inline
Chris@16 632 typename boost::result_of<F(value_type&)>::type
Chris@16 633 operator()(BOOST_THREAD_RV_REF(F) fct)
Chris@16 634 {
Chris@16 635 strict_lock<mutex_type> lk(mtx_);
Chris@16 636 return fct(value_);
Chris@16 637 }
Chris@16 638 template <typename F>
Chris@16 639 inline
Chris@16 640 typename boost::result_of<F(value_type const&)>::type
Chris@16 641 operator()(BOOST_THREAD_RV_REF(F) fct) const
Chris@16 642 {
Chris@16 643 strict_lock<mutex_type> lk(mtx_);
Chris@16 644 return fct(value_);
Chris@16 645 }
Chris@16 646
Chris@16 647
Chris@16 648 #if defined BOOST_NO_CXX11_RVALUE_REFERENCES
Chris@16 649 template <typename F>
Chris@16 650 inline
Chris@16 651 typename boost::result_of<F(value_type&)>::type
Chris@16 652 operator()(F const & fct)
Chris@16 653 {
Chris@16 654 strict_lock<mutex_type> lk(mtx_);
Chris@16 655 return fct(value_);
Chris@16 656 }
Chris@16 657 template <typename F>
Chris@16 658 inline
Chris@16 659 typename boost::result_of<F(value_type const&)>::type
Chris@16 660 operator()(F const & fct) const
Chris@16 661 {
Chris@16 662 strict_lock<mutex_type> lk(mtx_);
Chris@16 663 return fct(value_);
Chris@16 664 }
Chris@16 665
Chris@16 666 template <typename R>
Chris@16 667 inline
Chris@16 668 R operator()(R(*fct)(value_type&))
Chris@16 669 {
Chris@16 670 strict_lock<mutex_type> lk(mtx_);
Chris@16 671 return fct(value_);
Chris@16 672 }
Chris@16 673 template <typename R>
Chris@16 674 inline
Chris@16 675 R operator()(R(*fct)(value_type const&)) const
Chris@16 676 {
Chris@16 677 strict_lock<mutex_type> lk(mtx_);
Chris@16 678 return fct(value_);
Chris@16 679 }
Chris@16 680 #endif
Chris@16 681
Chris@16 682
Chris@16 683 /**
Chris@16 684 * The synchronize() factory make easier to lock on a scope.
Chris@16 685 * As discussed, operator-> can only lock over the duration of a call, so it is insufficient for complex operations.
Chris@16 686 * With synchronize() you get to lock the object in a scoped and to directly access the object inside that scope.
Chris@16 687 *
Chris@16 688 * Example
Chris@16 689 * void fun(synchronized_value<vector<int>> & v) {
Chris@16 690 * auto&& vec=v.synchronize();
Chris@16 691 * vec.push_back(42);
Chris@16 692 * assert(vec.back() == 42);
Chris@16 693 * }
Chris@16 694 */
Chris@16 695 strict_lock_ptr<T,Lockable> synchronize()
Chris@16 696 {
Chris@16 697 return BOOST_THREAD_MAKE_RV_REF((strict_lock_ptr<T,Lockable>(value_, mtx_)));
Chris@16 698 }
Chris@16 699 const_strict_lock_ptr<T,Lockable> synchronize() const
Chris@16 700 {
Chris@16 701 return BOOST_THREAD_MAKE_RV_REF((const_strict_lock_ptr<T,Lockable>(value_, mtx_)));
Chris@16 702 }
Chris@16 703
Chris@16 704 unique_lock_ptr<T,Lockable> unique_synchronize()
Chris@16 705 {
Chris@16 706 return BOOST_THREAD_MAKE_RV_REF((unique_lock_ptr<T,Lockable>(value_, mtx_)));
Chris@16 707 }
Chris@16 708 const_unique_lock_ptr<T,Lockable> unique_synchronize() const
Chris@16 709 {
Chris@16 710 return BOOST_THREAD_MAKE_RV_REF((const_unique_lock_ptr<T,Lockable>(value_, mtx_)));
Chris@16 711 }
Chris@16 712 unique_lock_ptr<T,Lockable> unique_synchronize(defer_lock_t tag)
Chris@16 713 {
Chris@16 714 return BOOST_THREAD_MAKE_RV_REF((unique_lock_ptr<T,Lockable>(value_, mtx_, tag)));
Chris@16 715 }
Chris@16 716 const_unique_lock_ptr<T,Lockable> unique_synchronize(defer_lock_t tag) const
Chris@16 717 {
Chris@16 718 return BOOST_THREAD_MAKE_RV_REF((const_unique_lock_ptr<T,Lockable>(value_, mtx_, tag)));
Chris@16 719 }
Chris@16 720 unique_lock_ptr<T,Lockable> defer_synchronize() BOOST_NOEXCEPT
Chris@16 721 {
Chris@16 722 return BOOST_THREAD_MAKE_RV_REF((unique_lock_ptr<T,Lockable>(value_, mtx_, defer_lock)));
Chris@16 723 }
Chris@16 724 const_unique_lock_ptr<T,Lockable> defer_synchronize() const BOOST_NOEXCEPT
Chris@16 725 {
Chris@16 726 return BOOST_THREAD_MAKE_RV_REF((const_unique_lock_ptr<T,Lockable>(value_, mtx_, defer_lock)));
Chris@16 727 }
Chris@16 728 unique_lock_ptr<T,Lockable> try_to_synchronize() BOOST_NOEXCEPT
Chris@16 729 {
Chris@16 730 return BOOST_THREAD_MAKE_RV_REF((unique_lock_ptr<T,Lockable>(value_, mtx_, try_to_lock)));
Chris@16 731 }
Chris@16 732 const_unique_lock_ptr<T,Lockable> try_to_synchronize() const BOOST_NOEXCEPT
Chris@16 733 {
Chris@16 734 return BOOST_THREAD_MAKE_RV_REF((const_unique_lock_ptr<T,Lockable>(value_, mtx_, try_to_lock)));
Chris@16 735 }
Chris@16 736 unique_lock_ptr<T,Lockable> adopt_synchronize() BOOST_NOEXCEPT
Chris@16 737 {
Chris@16 738 return BOOST_THREAD_MAKE_RV_REF((unique_lock_ptr<T,Lockable>(value_, mtx_, adopt_lock)));
Chris@16 739 }
Chris@16 740 const_unique_lock_ptr<T,Lockable> adopt_synchronize() const BOOST_NOEXCEPT
Chris@16 741 {
Chris@16 742 return BOOST_THREAD_MAKE_RV_REF((const_unique_lock_ptr<T,Lockable>(value_, mtx_, adopt_lock)));
Chris@16 743 }
Chris@16 744
Chris@16 745
Chris@16 746 #if ! defined __IBMCPP__
Chris@16 747 private:
Chris@16 748 #endif
Chris@16 749 class deref_value
Chris@16 750 {
Chris@16 751 private:
Chris@16 752 friend class synchronized_value;
Chris@16 753
Chris@16 754 boost::unique_lock<mutex_type> lk_;
Chris@16 755 T& value_;
Chris@16 756
Chris@16 757 explicit deref_value(synchronized_value& outer):
Chris@16 758 lk_(outer.mtx_),value_(outer.value_)
Chris@16 759 {}
Chris@16 760
Chris@16 761 public:
Chris@16 762 BOOST_THREAD_MOVABLE_ONLY(deref_value)
Chris@16 763
Chris@16 764 deref_value(BOOST_THREAD_RV_REF(deref_value) other):
Chris@16 765 lk_(boost::move(BOOST_THREAD_RV(other).lk_)),value_(BOOST_THREAD_RV(other).value_)
Chris@16 766 {}
Chris@16 767 operator T&()
Chris@16 768 {
Chris@16 769 return value_;
Chris@16 770 }
Chris@16 771
Chris@16 772 deref_value& operator=(T const& newVal)
Chris@16 773 {
Chris@16 774 value_=newVal;
Chris@16 775 return *this;
Chris@16 776 }
Chris@16 777 };
Chris@16 778 class const_deref_value
Chris@16 779 {
Chris@16 780 private:
Chris@16 781 friend class synchronized_value;
Chris@16 782
Chris@16 783 boost::unique_lock<mutex_type> lk_;
Chris@16 784 const T& value_;
Chris@16 785
Chris@16 786 explicit const_deref_value(synchronized_value const& outer):
Chris@16 787 lk_(outer.mtx_), value_(outer.value_)
Chris@16 788 {}
Chris@16 789
Chris@16 790 public:
Chris@16 791 BOOST_THREAD_MOVABLE_ONLY(const_deref_value)
Chris@16 792
Chris@16 793 const_deref_value(BOOST_THREAD_RV_REF(const_deref_value) other):
Chris@16 794 lk_(boost::move(BOOST_THREAD_RV(other).lk_)), value_(BOOST_THREAD_RV(other).value_)
Chris@16 795 {}
Chris@16 796
Chris@16 797 operator const T&()
Chris@16 798 {
Chris@16 799 return value_;
Chris@16 800 }
Chris@16 801 };
Chris@16 802
Chris@16 803 public:
Chris@16 804 deref_value operator*()
Chris@16 805 {
Chris@16 806 return BOOST_THREAD_MAKE_RV_REF(deref_value(*this));
Chris@16 807 }
Chris@16 808
Chris@16 809 const_deref_value operator*() const
Chris@16 810 {
Chris@16 811 return BOOST_THREAD_MAKE_RV_REF(const_deref_value(*this));
Chris@16 812 }
Chris@16 813
Chris@16 814 // io functions
Chris@16 815 /**
Chris@16 816 * @requires T is OutputStreamable
Chris@16 817 * @effects saves the value type on the output stream @c os.
Chris@16 818 */
Chris@16 819 template <typename OStream>
Chris@16 820 void save(OStream& os) const
Chris@16 821 {
Chris@16 822 strict_lock<mutex_type> lk(mtx_);
Chris@16 823 os << value_;
Chris@16 824 }
Chris@16 825 /**
Chris@16 826 * @requires T is InputStreamable
Chris@16 827 * @effects loads the value type from the input stream @c is.
Chris@16 828 */
Chris@16 829 template <typename IStream>
Chris@16 830 void load(IStream& is) const
Chris@16 831 {
Chris@16 832 strict_lock<mutex_type> lk(mtx_);
Chris@16 833 is >> value_;
Chris@16 834 }
Chris@16 835
Chris@16 836 // relational operators
Chris@16 837 /**
Chris@16 838 * @requires T is EqualityComparable
Chris@16 839 *
Chris@16 840 */
Chris@16 841 bool operator==(synchronized_value const& rhs) const
Chris@16 842 {
Chris@16 843 unique_lock<mutex_type> lk1(mtx_, defer_lock);
Chris@16 844 unique_lock<mutex_type> lk2(rhs.mtx_, defer_lock);
Chris@16 845 lock(lk1,lk2);
Chris@16 846
Chris@16 847 return value_ == rhs.value_;
Chris@16 848 }
Chris@16 849 /**
Chris@16 850 * @requires T is LessThanComparable
Chris@16 851 *
Chris@16 852 */
Chris@16 853 bool operator<(synchronized_value const& rhs) const
Chris@16 854 {
Chris@16 855 unique_lock<mutex_type> lk1(mtx_, defer_lock);
Chris@16 856 unique_lock<mutex_type> lk2(rhs.mtx_, defer_lock);
Chris@16 857 lock(lk1,lk2);
Chris@16 858
Chris@16 859 return value_ < rhs.value_;
Chris@16 860 }
Chris@16 861 /**
Chris@16 862 * @requires T is GreaterThanComparable
Chris@16 863 *
Chris@16 864 */
Chris@16 865 bool operator>(synchronized_value const& rhs) const
Chris@16 866 {
Chris@16 867 unique_lock<mutex_type> lk1(mtx_, defer_lock);
Chris@16 868 unique_lock<mutex_type> lk2(rhs.mtx_, defer_lock);
Chris@16 869 lock(lk1,lk2);
Chris@16 870
Chris@16 871 return value_ > rhs.value_;
Chris@16 872 }
Chris@16 873 bool operator<=(synchronized_value const& rhs) const
Chris@16 874 {
Chris@16 875 unique_lock<mutex_type> lk1(mtx_, defer_lock);
Chris@16 876 unique_lock<mutex_type> lk2(rhs.mtx_, defer_lock);
Chris@16 877 lock(lk1,lk2);
Chris@16 878
Chris@16 879 return value_ <= rhs.value_;
Chris@16 880 }
Chris@16 881 bool operator>=(synchronized_value const& rhs) const
Chris@16 882 {
Chris@16 883 unique_lock<mutex_type> lk1(mtx_, defer_lock);
Chris@16 884 unique_lock<mutex_type> lk2(rhs.mtx_, defer_lock);
Chris@16 885 lock(lk1,lk2);
Chris@16 886
Chris@16 887 return value_ >= rhs.value_;
Chris@16 888 }
Chris@16 889 bool operator==(value_type const& rhs) const
Chris@16 890 {
Chris@16 891 unique_lock<mutex_type> lk1(mtx_);
Chris@16 892
Chris@16 893 return value_ == rhs;
Chris@16 894 }
Chris@16 895 bool operator!=(value_type const& rhs) const
Chris@16 896 {
Chris@16 897 unique_lock<mutex_type> lk1(mtx_);
Chris@16 898
Chris@16 899 return value_ != rhs;
Chris@16 900 }
Chris@16 901 bool operator<(value_type const& rhs) const
Chris@16 902 {
Chris@16 903 unique_lock<mutex_type> lk1(mtx_);
Chris@16 904
Chris@16 905 return value_ < rhs;
Chris@16 906 }
Chris@16 907 bool operator<=(value_type const& rhs) const
Chris@16 908 {
Chris@16 909 unique_lock<mutex_type> lk1(mtx_);
Chris@16 910
Chris@16 911 return value_ <= rhs;
Chris@16 912 }
Chris@16 913 bool operator>(value_type const& rhs) const
Chris@16 914 {
Chris@16 915 unique_lock<mutex_type> lk1(mtx_);
Chris@16 916
Chris@16 917 return value_ > rhs;
Chris@16 918 }
Chris@16 919 bool operator>=(value_type const& rhs) const
Chris@16 920 {
Chris@16 921 unique_lock<mutex_type> lk1(mtx_);
Chris@16 922
Chris@16 923 return value_ >= rhs;
Chris@16 924 }
Chris@16 925
Chris@16 926 };
Chris@16 927
Chris@16 928 // Specialized algorithms
Chris@16 929 /**
Chris@16 930 *
Chris@16 931 */
Chris@16 932 template <typename T, typename L>
Chris@16 933 inline void swap(synchronized_value<T,L> & lhs, synchronized_value<T,L> & rhs)
Chris@16 934 {
Chris@16 935 lhs.swap(rhs);
Chris@16 936 }
Chris@16 937 template <typename T, typename L>
Chris@16 938 inline void swap(synchronized_value<T,L> & lhs, T & rhs)
Chris@16 939 {
Chris@16 940 lhs.swap(rhs);
Chris@16 941 }
Chris@16 942 template <typename T, typename L>
Chris@16 943 inline void swap(T & lhs, synchronized_value<T,L> & rhs)
Chris@16 944 {
Chris@16 945 rhs.swap(lhs);
Chris@16 946 }
Chris@16 947
Chris@16 948 //Hash support
Chris@16 949
Chris@16 950 // template <class T> struct hash;
Chris@16 951 // template <typename T, typename L>
Chris@16 952 // struct hash<synchronized_value<T,L> >;
Chris@16 953
Chris@16 954 // Comparison with T
Chris@16 955 template <typename T, typename L>
Chris@16 956 bool operator!=(synchronized_value<T,L> const&lhs, synchronized_value<T,L> const& rhs)
Chris@16 957 {
Chris@16 958 return ! (lhs==rhs);
Chris@16 959 }
Chris@16 960
Chris@16 961 template <typename T, typename L>
Chris@16 962 bool operator==(T const& lhs, synchronized_value<T,L> const&rhs)
Chris@16 963 {
Chris@16 964 return rhs==lhs;
Chris@16 965 }
Chris@16 966 template <typename T, typename L>
Chris@16 967 bool operator!=(T const& lhs, synchronized_value<T,L> const&rhs)
Chris@16 968 {
Chris@16 969 return rhs!=lhs;
Chris@16 970 }
Chris@16 971 template <typename T, typename L>
Chris@16 972 bool operator<(T const& lhs, synchronized_value<T,L> const&rhs)
Chris@16 973 {
Chris@16 974 return rhs>=lhs;
Chris@16 975 }
Chris@16 976 template <typename T, typename L>
Chris@16 977 bool operator<=(T const& lhs, synchronized_value<T,L> const&rhs)
Chris@16 978 {
Chris@16 979 return rhs>lhs;
Chris@16 980 }
Chris@16 981 template <typename T, typename L>
Chris@16 982 bool operator>(T const& lhs, synchronized_value<T,L> const&rhs)
Chris@16 983 {
Chris@16 984 return rhs<=lhs;
Chris@16 985 }
Chris@16 986 template <typename T, typename L>
Chris@16 987 bool operator>=(T const& lhs, synchronized_value<T,L> const&rhs)
Chris@16 988 {
Chris@16 989 return rhs<lhs;
Chris@16 990 }
Chris@16 991
Chris@16 992 /**
Chris@16 993 *
Chris@16 994 */
Chris@16 995 template <typename OStream, typename T, typename L>
Chris@16 996 inline OStream& operator<<(OStream& os, synchronized_value<T,L> const& rhs)
Chris@16 997 {
Chris@16 998 rhs.save(os);
Chris@16 999 return os;
Chris@16 1000 }
Chris@16 1001 template <typename IStream, typename T, typename L>
Chris@16 1002 inline IStream& operator>>(IStream& is, synchronized_value<T,L> const& rhs)
Chris@16 1003 {
Chris@16 1004 rhs.load(is);
Chris@16 1005 return is;
Chris@16 1006 }
Chris@16 1007
Chris@16 1008 #if ! defined(BOOST_THREAD_NO_SYNCHRONIZE)
Chris@16 1009 #if ! defined BOOST_NO_CXX11_VARIADIC_TEMPLATES
Chris@16 1010
Chris@16 1011 template <typename ...SV>
Chris@16 1012 std::tuple<typename synchronized_value_strict_lock_ptr<SV>::type ...> synchronize(SV& ...sv)
Chris@16 1013 {
Chris@16 1014 boost::lock(sv.mtx_ ...);
Chris@16 1015 typedef std::tuple<typename synchronized_value_strict_lock_ptr<SV>::type ...> t_type;
Chris@16 1016
Chris@16 1017 return t_type(typename synchronized_value_strict_lock_ptr<SV>::type(sv.value_, sv.mtx_, adopt_lock) ...);
Chris@16 1018 }
Chris@16 1019 #else
Chris@16 1020
Chris@16 1021 template <typename SV1, typename SV2>
Chris@16 1022 std::tuple<
Chris@16 1023 typename synchronized_value_strict_lock_ptr<SV1>::type,
Chris@16 1024 typename synchronized_value_strict_lock_ptr<SV2>::type
Chris@16 1025 >
Chris@16 1026 synchronize(SV1& sv1, SV2& sv2)
Chris@16 1027 {
Chris@16 1028 boost::lock(sv1.mtx_, sv2.mtx_);
Chris@16 1029 typedef std::tuple<
Chris@16 1030 typename synchronized_value_strict_lock_ptr<SV1>::type,
Chris@16 1031 typename synchronized_value_strict_lock_ptr<SV2>::type
Chris@16 1032 > t_type;
Chris@16 1033
Chris@16 1034 return t_type(
Chris@16 1035 typename synchronized_value_strict_lock_ptr<SV1>::type(sv1.value_, sv1.mtx_, adopt_lock),
Chris@16 1036 typename synchronized_value_strict_lock_ptr<SV2>::type(sv2.value_, sv2.mtx_, adopt_lock)
Chris@16 1037 );
Chris@16 1038
Chris@16 1039 }
Chris@16 1040 template <typename SV1, typename SV2, typename SV3>
Chris@16 1041 std::tuple<
Chris@16 1042 typename synchronized_value_strict_lock_ptr<SV1>::type,
Chris@16 1043 typename synchronized_value_strict_lock_ptr<SV2>::type,
Chris@16 1044 typename synchronized_value_strict_lock_ptr<SV3>::type
Chris@16 1045 >
Chris@16 1046 synchronize(SV1& sv1, SV2& sv2, SV3& sv3)
Chris@16 1047 {
Chris@16 1048 boost::lock(sv1.mtx_, sv2.mtx_);
Chris@16 1049 typedef std::tuple<
Chris@16 1050 typename synchronized_value_strict_lock_ptr<SV1>::type,
Chris@16 1051 typename synchronized_value_strict_lock_ptr<SV2>::type,
Chris@16 1052 typename synchronized_value_strict_lock_ptr<SV3>::type
Chris@16 1053 > t_type;
Chris@16 1054
Chris@16 1055 return t_type(
Chris@16 1056 typename synchronized_value_strict_lock_ptr<SV1>::type(sv1.value_, sv1.mtx_, adopt_lock),
Chris@16 1057 typename synchronized_value_strict_lock_ptr<SV2>::type(sv2.value_, sv2.mtx_, adopt_lock),
Chris@16 1058 typename synchronized_value_strict_lock_ptr<SV3>::type(sv3.value_, sv3.mtx_, adopt_lock)
Chris@16 1059 );
Chris@16 1060
Chris@16 1061 }
Chris@16 1062 #endif
Chris@16 1063 #endif
Chris@16 1064 }
Chris@16 1065
Chris@16 1066 #include <boost/config/abi_suffix.hpp>
Chris@16 1067
Chris@16 1068 #endif // header