$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r81087 - in trunk: boost/thread libs/thread/example
From: vicente.botet_at_[hidden]
Date: 2012-10-28 21:09:59
Author: viboes
Date: 2012-10-28 21:09:58 EDT (Sun, 28 Oct 2012)
New Revision: 81087
URL: http://svn.boost.org/trac/boost/changeset/81087
Log:
Thread: Added externally_locked
Added:
   trunk/boost/thread/externally_locked.hpp   (contents, props changed)
   trunk/libs/thread/example/ba_externallly_locked.cpp   (contents, props changed)
Added: trunk/boost/thread/externally_locked.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/thread/externally_locked.hpp	2012-10-28 21:09:58 EDT (Sun, 28 Oct 2012)
@@ -0,0 +1,320 @@
+// (C) Copyright 2012 Vicente J. Botet Escriba
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_THREAD_EXTERNALLY_LOCKED_HPP
+#define BOOST_THREAD_EXTERNALLY_LOCKED_HPP
+
+#include <boost/thread/detail/config.hpp>
+
+#include <boost/thread/exceptions.hpp>
+#include <boost/thread/lock_concepts.hpp>
+#include <boost/thread/lock_traits.hpp>
+#include <boost/thread/lockable_concepts.hpp>
+#include <boost/thread/strict_lock.hpp>
+
+#include <boost/static_assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/utility/swap.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+
+  /**
+   * externally_locked cloaks an object of type T, and actually provides full
+   * access to that object through the get and set member functions, provided you
+   * pass a reference to a strict lock object
+   */
+
+  //[externally_locked
+  template <typename T, typename MutexType = boost::mutex>
+  class externally_locked
+  {
+    //BOOST_CONCEPT_ASSERT(( CopyConstructible<T> ));
+    BOOST_CONCEPT_ASSERT(( BasicLockable<MutexType> ));
+
+  public:
+    typedef MutexType mutex_type;
+
+    BOOST_THREAD_COPYABLE_AND_MOVABLE( externally_locked )
+    /**
+     * Requires: T is a model of CopyConstructible.
+     * Effects: Constructs an externally locked object copying the cloaked type.
+     */
+    BOOST_CONSTEXPR externally_locked(mutex_type& mtx, const T& obj) :
+      obj_(obj), mtx_(&mtx)
+    {
+    }
+
+    /**
+     * Requires: T is a model of Movable.
+     * Effects: Constructs an externally locked object copying the cloaked type.
+     */
+    BOOST_CONSTEXPR externally_locked(mutex_type& mtx, BOOST_THREAD_RV_REF(T) obj) :
+      obj_(move(obj)), mtx_(&mtx)
+    {
+    }
+
+    /**
+     * Requires: T is a model of DefaultConstructible.
+     * Effects: Constructs an externally locked object initializing the cloaked type with the default constructor.
+     */
+    externally_locked(mutex_type& mtx) :
+      obj_(), mtx_(&mtx)
+    {
+    }
+
+    /**
+     *  Move constructor
+     */
+    externally_locked(BOOST_THREAD_RV_REF(externally_locked) rhs) :
+    obj_(move(rhs.obj_)), mtx_(rhs.mtx_)
+    {
+      rhs.mtx_=0;
+    }
+
+    /**
+     * Requires: The lk parameter must be locking the associated mtx.
+     *
+     * Returns: The address of the cloaked object..
+     *
+     * Throws: lock_error if BOOST_THREAD_EXTERNALLY_LOCKED_DONT_CHECK_SAME is not defined and the lk parameter doesn't satisfy the preconditions
+     */
+    T& get(strict_lock<mutex_type>& lk)
+    {
+
+#ifndef BOOST_THREAD_EXTERNALLY_LOCKED_DONT_CHECK_SAME  /*< define BOOST_THREAD_EXTERNALLY_LOCKED_DONT_CHECK_SAME if you don't want to check lk check the same mtx >*/
+      if (lk.mutex()!=mtx_) throw lock_error(); /*< run time check throw if not locks the same >*/
+#endif
+      return obj_;
+    }
+
+    const T& get(strict_lock<mutex_type>& lk) const
+    {
+
+#ifndef BOOST_THREAD_EXTERNALLY_LOCKED_DONT_CHECK_SAME  /*< define BOOST_THREAD_EXTERNALLY_LOCKED_DONT_CHECK_SAME if you don't want to check lk check the same mtx >*/
+      if (lk.mutex()!=mtx_) throw lock_error(); /*< run time check throw if not locks the same >*/
+#endif
+      return obj_;
+    }
+
+    template <class Lock>
+    T& get(nested_strict_lock<Lock>& lk)
+    {
+      BOOST_STATIC_ASSERT( (is_same<mutex_type, typename Lock::mutex_type>::value)); /*< that locks the same type >*/
+
+#ifndef BOOST_THREAD_EXTERNALLY_LOCKED_DONT_CHECK_SAME  /*< define BOOST_THREAD_EXTERNALLY_LOCKED_DONT_CHECK_SAME if you don't want to check lk check the same mtx >*/
+      if (lk.mutex()!=mtx_) throw lock_error(); /*< run time check throw if not locks the same >*/
+#endif
+      return obj_;
+    }
+
+    template <class Lock>
+    const T& get(nested_strict_lock<Lock>& lk) const
+    {
+      BOOST_STATIC_ASSERT( (is_same<mutex_type, typename Lock::mutex_type>::value)); /*< that locks the same type >*/
+
+#ifndef BOOST_THREAD_EXTERNALLY_LOCKED_DONT_CHECK_SAME  /*< define BOOST_THREAD_EXTERNALLY_LOCKED_DONT_CHECK_SAME if you don't want to check lk check the same mtx >*/
+      if (lk.mutex()!=mtx_) throw lock_error(); /*< run time check throw if not locks the same >*/
+#endif
+      return obj_;
+    }
+
+    /**
+     * Requires: The lk parameter must be locking the associated mtx.
+     * Returns: The address of the cloaked object..
+     *
+     * Throws: lock_error if BOOST_THREAD_EXTERNALLY_LOCKED_DONT_CHECK_SAME is not defined and the lk parameter doesn't satisfy the preconditions
+     */
+    template <class Lock>
+    T& get(Lock& lk)
+    {
+      BOOST_CONCEPT_ASSERT(( StrictLock<Lock> ));
+      BOOST_STATIC_ASSERT( (is_strict_lock<Lock>::value)); /*< lk is a strict lock "sur parolle" >*/
+      BOOST_STATIC_ASSERT( (is_same<mutex_type, typename Lock::mutex_type>::value)); /*< that locks the same type >*/
+
+#ifndef BOOST_THREAD_EXTERNALLY_LOCKED_DONT_CHECK_OWNERSHIP  /*< define BOOST_THREAD_EXTERNALLY_LOCKED_NO_CHECK_OWNERSHIP if you don't want to check lock ownership >*/
+      if (!lk.own_lock()) throw lock_error(); /*< run time check throw if no locked >*/
+#endif
+#ifndef BOOST_THREAD_EXTERNALLY_LOCKED_DONT_CHECK_SAME
+      if (lk.mutex()!=mtx_) throw lock_error();
+#endif
+      return obj_;
+    }
+
+    mutex_type* mutex()
+    {
+      return mtx_;
+    }
+
+    // modifiers
+
+    void lock()
+    {
+      mtx_->lock();
+    }
+    void unlock()
+    {
+      mtx_->unlock();
+    }
+    bool try_lock()
+    {
+      return mtx_->try_lock();
+    }
+    // todo add time related functions
+
+  private:
+    T obj_;
+    mutex_type* mtx_;
+  };
+  //]
+
+  /**
+   * externally_locked<T&,M> specialization for T& that cloaks an reference to an object of type T, and actually
+   * provides full access to that object through the get and set member functions, provided you
+   * pass a reference to a strict lock object.
+   */
+
+  //[externally_locked_ref
+  template <typename T, typename MutexType>
+  class externally_locked<T&, MutexType>
+  {
+    //BOOST_CONCEPT_ASSERT(( CopyConstructible<T> ));
+    BOOST_CONCEPT_ASSERT(( BasicLockable<MutexType> ));
+
+  public:
+    typedef MutexType mutex_type;
+
+    BOOST_THREAD_MOVABLE_ONLY( externally_locked )
+
+    /**
+     * Effects: Constructs an externally locked object storing the cloaked reference object.
+     */
+    externally_locked(T& obj, mutex_type& mtx) :
+      obj_(&obj), mtx_(&mtx)
+    {
+    }
+
+    /// move constructor
+    externally_locked(BOOST_THREAD_RV_REF(externally_locked) rhs) :
+    obj_(rhs.obj_), mtx_(rhs.mtx_)
+    {
+      rhs.obj_=0;
+      rhs.mtx_=0;
+    }
+
+    void swap(externally_locked& rhs)
+    {
+      swap(obj_, rhs.obj_);
+      swap(mtx_, rhs.mtx_);
+    }
+    /**
+     * Requires: The lk parameter must be locking the associated mtx.
+     *
+     * Returns: The address of the cloaked object..
+     *
+     * Throws: lock_error if BOOST_THREAD_EXTERNALLY_LOCKED_DONT_CHECK_SAME is not defined and the lk parameter doesn't satisfy the preconditions
+     */
+    T& get(strict_lock<mutex_type>& lk)
+    {
+
+#ifndef BOOST_THREAD_EXTERNALLY_LOCKED_DONT_CHECK_SAME  /*< define BOOST_THREAD_EXTERNALLY_LOCKED_DONT_CHECK_SAME if you don't want to check lk check the same mtx >*/
+      if (lk.mutex()!=mtx_) throw lock_error(); /*< run time check throw if not locks the same >*/
+#endif
+      return *obj_;
+    }
+
+    const T& get(strict_lock<mutex_type>& lk) const
+    {
+
+#ifndef BOOST_THREAD_EXTERNALLY_LOCKED_DONT_CHECK_SAME  /*< define BOOST_THREAD_EXTERNALLY_LOCKED_DONT_CHECK_SAME if you don't want to check lk check the same mtx >*/
+      if (lk.mutex()!=mtx_) throw lock_error(); /*< run time check throw if not locks the same >*/
+#endif
+      return *obj_;
+    }
+
+    template <class Lock>
+    T& get(nested_strict_lock<Lock>& lk)
+    {
+      BOOST_STATIC_ASSERT( (is_same<mutex_type, typename Lock::mutex_type>::value)); /*< that locks the same type >*/
+
+#ifndef BOOST_THREAD_EXTERNALLY_LOCKED_DONT_CHECK_SAME  /*< define BOOST_THREAD_EXTERNALLY_LOCKED_DONT_CHECK_SAME if you don't want to check lk check the same mtx >*/
+      if (lk.mutex()!=mtx_) throw lock_error(); /*< run time check throw if not locks the same >*/
+#endif
+      return *obj_;
+    }
+
+    template <class Lock>
+    const T& get(nested_strict_lock<Lock>& lk) const
+    {
+      BOOST_STATIC_ASSERT( (is_same<mutex_type, typename Lock::mutex_type>::value)); /*< that locks the same type >*/
+
+#ifndef BOOST_THREAD_EXTERNALLY_LOCKED_DONT_CHECK_SAME  /*< define BOOST_THREAD_EXTERNALLY_LOCKED_DONT_CHECK_SAME if you don't want to check lk check the same mtx >*/
+      if (!lk.is_locking(&mtx_)) throw lock_error(); /*< run time check throw if not locks the same >*/
+#endif
+      return *obj_;
+    }
+
+    /**
+     * Requires: The lk parameter must be locking the associated mtx.
+     * Returns: The address of the cloaked object..
+     *
+     * Throws: lock_error if BOOST_THREAD_EXTERNALLY_LOCKED_DONT_CHECK_SAME is not defined and the lk parameter doesn't satisfy the preconditions
+     */
+    template <class Lock>
+    T& get(Lock& lk)
+    {
+      BOOST_CONCEPT_ASSERT(( StrictLock<Lock> ));
+      BOOST_STATIC_ASSERT( (is_strict_lock<Lock>::value)); /*< lk is a strict lock "sur parolle" >*/
+      BOOST_STATIC_ASSERT( (is_same<mutex_type, typename Lock::mutex_type>::value)); /*< that locks the same type >*/
+
+#ifndef BOOST_THREAD_EXTERNALLY_LOCKED_DONT_CHECK_OWNERSHIP  /*< define BOOST_THREAD_EXTERNALLY_LOCKED_NO_CHECK_OWNERSHIP if you don't want to check lock ownership >*/
+      if (!lk.own_lock()) throw lock_error(); /*< run time check throw if no locked >*/
+#endif
+#ifndef BOOST_THREAD_EXTERNALLY_LOCKED_DONT_CHECK_SAME
+      if (lk.mutex()!=mtx_) throw lock_error();
+#endif
+      return *obj_;
+    }
+
+    mutex_type* mutex()
+    {
+      return mtx_;
+    }
+
+    void lock()
+    {
+      mtx_->lock();
+    }
+    void unlock()
+    {
+      mtx_->unlock();
+    }
+    bool try_lock()
+    {
+      return mtx_->try_lock();
+    }
+    // todo add time related functions
+
+  protected:
+    T* obj_;
+    mutex_type* mtx_;
+  };
+  //]
+
+  template <typename T, typename MutexType>
+  void swap(externally_locked<T, MutexType> & lhs, externally_locked<T, MutexType> & rhs)
+  {
+    lhs.swap(rhs);
+  }
+
+}
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif // header
Added: trunk/libs/thread/example/ba_externallly_locked.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/thread/example/ba_externallly_locked.cpp	2012-10-28 21:09:58 EDT (Sun, 28 Oct 2012)
@@ -0,0 +1,115 @@
+// Copyright (C) 2012 Vicente Botet
+//
+//  Distributed under the Boost Software License, Version 1.0. (See accompanying
+//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#define BOOST_THREAD_VERSION 4
+
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/externally_locked.hpp>
+#include <boost/thread/strict_lock.hpp>
+#include <boost/thread/lock_types.hpp>
+#include <iostream>
+
+using namespace boost;
+
+class BankAccount
+{
+  int balance_;
+public:
+  void Deposit(int amount)
+  {
+    balance_ += amount;
+  }
+  void Withdraw(int amount)
+  {
+    balance_ -= amount;
+  }
+  int GetBalance()
+  {
+    return balance_;
+  }
+};
+
+//[AccountManager
+class AccountManager
+{
+  mutex mtx_;
+public:
+  AccountManager() :
+    checkingAcct_(mtx_), savingsAcct_(mtx_)
+  {
+  }
+  inline void Checking2Savings(int amount);
+  inline void AMoreComplicatedChecking2Savings(int amount);
+private:
+  /*<-*/
+  bool some_condition()
+  {
+    return true;
+  } /*->*/
+  externally_locked<BankAccount, mutex > checkingAcct_;
+  externally_locked<BankAccount, mutex > savingsAcct_;
+};
+//]
+
+//[Checking2Savings
+void AccountManager::Checking2Savings(int amount)
+{
+  strict_lock<mutex> guard(mtx_);
+  checkingAcct_.get(guard).Withdraw(amount);
+  savingsAcct_.get(guard).Deposit(amount);
+}
+//]
+
+#if MUST_NOT_COMPILE
+//[AMoreComplicatedChecking2Savings_DO_NOT_COMPILE
+void AccountManager::AMoreComplicatedChecking2Savings(int amount) {
+    unique_lock<mutex> guard(mtx_);
+    if (some_condition()) {
+        guard.lock();
+    }
+    checkingAcct_.get(guard).Withdraw(amount);
+    savingsAcct_.get(guard).Deposit(amount);
+    guard1.unlock();
+}
+//]
+#elif MUST_NOT_COMPILE_2
+//[AMoreComplicatedChecking2Savings_DO_NOT_COMPILE2
+void AccountManager::AMoreComplicatedChecking2Savings(int amount) {
+    unique_lock<mutex> guard1(mtx_);
+    if (some_condition()) {
+        guard1.lock();
+    }
+    {
+        strict_lock<mutex> guard(guard1);
+        checkingAcct_.get(guard).Withdraw(amount);
+        savingsAcct_.get(guard).Deposit(amount);
+    }
+    guard1.unlock();
+}
+]
+#else
+//[AMoreComplicatedChecking2Savings
+void AccountManager::AMoreComplicatedChecking2Savings(int amount) {
+    unique_lock<mutex> guard1(mtx_);
+    if (some_condition()) {
+        guard1.lock();
+    }
+    {
+        nested_strict_lock<unique_lock<mutex> > guard(guard1);
+        checkingAcct_.get(guard).Withdraw(amount);
+        savingsAcct_.get(guard).Deposit(amount);
+    }
+    guard1.unlock();
+}
+//]
+#endif
+
+int main()
+{
+  AccountManager mgr;
+  mgr.Checking2Savings(100);
+  return 0;
+}
+