Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r85306 - in trunk: boost/thread libs/thread/test libs/thread/test/sync/mutual_exclusion/synchronized_value
From: vicente.botet_at_[hidden]
Date: 2013-08-11 16:33:48


Author: viboes
Date: 2013-08-11 16:33:47 EDT (Sun, 11 Aug 2013)
New Revision: 85306
URL: http://svn.boost.org/trac/boost/changeset/85306

Log:
Thread: Added synchronized_value operator() to synchronize around a function call.

Added:
   trunk/libs/thread/test/sync/mutual_exclusion/synchronized_value/call_pass.cpp (contents, props changed)
Text files modified:
   trunk/boost/thread/synchronized_value.hpp | 83 ++++++++++++++++++++--
   trunk/libs/thread/test/Jamfile.v2 | 4
   trunk/libs/thread/test/sync/mutual_exclusion/synchronized_value/call_pass.cpp | 144 ++++++++++++++++++++++++++++++++++++++++
   3 files changed, 222 insertions(+), 9 deletions(-)

Modified: trunk/boost/thread/synchronized_value.hpp
==============================================================================
--- trunk/boost/thread/synchronized_value.hpp Sun Aug 11 14:50:04 2013 (r85305)
+++ trunk/boost/thread/synchronized_value.hpp 2013-08-11 16:33:47 EDT (Sun, 11 Aug 2013) (r85306)
@@ -26,10 +26,12 @@
 //#endif
 
 #if ! defined(BOOST_THREAD_NO_SYNCHRONIZE)
-#include <tuple> // todo change to <boost/tuple.hpp> once Boost.Tuple or Boost.Fusion provides Move semantics.
+#include <tuple> // todo change to <boost/tuple.hpp> once Boost.Tuple or Boost.Fusion provides Move semantics on C++98 compilers.
 #include <functional>
 #endif
 
+#include <boost/utility/result_of.hpp>
+
 #include <boost/config/abi_prefix.hpp>
 
 namespace boost
@@ -593,8 +595,6 @@
       boost::swap(value_, rhs);
     }
 
-
-
     /**
      * Essentially calling a method obj->foo(x, y, z) calls the method foo(x, y, z) inside a critical section as
      * long-lived as the call itself.
@@ -614,13 +614,80 @@
     }
 
     /**
+ * Call function on a locked block.
+ *
+ * @requires fct(value_) is well formed.
+ *
+ * Example
+ * void fun(synchronized_value<vector<int>> & v) {
+ * v ( [](vector<int>> & vec)
+ * {
+ * vec.push_back(42);
+ * assert(vec.back() == 42);
+ * } );
+ * }
+ */
+ template <typename F>
+ inline
+ typename boost::result_of<F(value_type&)>::type
+ operator()(BOOST_THREAD_RV_REF(F) fct)
+ {
+ strict_lock<mutex_type> lk(mtx_);
+ return fct(value_);
+ }
+ template <typename F>
+ inline
+ typename boost::result_of<F(value_type const&)>::type
+ operator()(BOOST_THREAD_RV_REF(F) fct) const
+ {
+ strict_lock<mutex_type> lk(mtx_);
+ return fct(value_);
+ }
+
+
+#if defined BOOST_NO_CXX11_RVALUE_REFERENCES
+ template <typename F>
+ inline
+ typename boost::result_of<F(value_type&)>::type
+ operator()(F const & fct)
+ {
+ strict_lock<mutex_type> lk(mtx_);
+ return fct(value_);
+ }
+ template <typename F>
+ inline
+ typename boost::result_of<F(value_type const&)>::type
+ operator()(F const & fct) const
+ {
+ strict_lock<mutex_type> lk(mtx_);
+ return fct(value_);
+ }
+
+ template <typename R>
+ inline
+ R operator()(R(*fct)(value_type&))
+ {
+ strict_lock<mutex_type> lk(mtx_);
+ return fct(value_);
+ }
+ template <typename R>
+ inline
+ R operator()(R(*fct)(value_type const&)) const
+ {
+ strict_lock<mutex_type> lk(mtx_);
+ return fct(value_);
+ }
+#endif
+
+
+ /**
      * The synchronize() factory make easier to lock on a scope.
      * As discussed, operator-> can only lock over the duration of a call, so it is insufficient for complex operations.
      * With synchronize() you get to lock the object in a scoped and to directly access the object inside that scope.
      *
      * Example
- * void fun(synchronized_value<vector<int>> & vec) {
- * auto&& vec=vec.synchronize();
+ * void fun(synchronized_value<vector<int>> & v) {
+ * auto&& vec=v.synchronize();
      * vec.push_back(42);
      * assert(vec.back() == 42);
      * }
@@ -880,9 +947,9 @@
 
   //Hash support
 
- template <class T> struct hash;
- template <typename T, typename L>
- struct hash<synchronized_value<T,L> >;
+// template <class T> struct hash;
+// template <typename T, typename L>
+// struct hash<synchronized_value<T,L> >;
 
   // Comparison with T
   template <typename T, typename L>

Modified: trunk/libs/thread/test/Jamfile.v2
==============================================================================
--- trunk/libs/thread/test/Jamfile.v2 Sun Aug 11 14:50:04 2013 (r85305)
+++ trunk/libs/thread/test/Jamfile.v2 2013-08-11 16:33:47 EDT (Sun, 11 Aug 2013) (r85306)
@@ -768,6 +768,7 @@
           [ thread-run2-noit ./sync/mutual_exclusion/synchronized_value/swap_pass.cpp : synchronized_value__swap_p ]
           [ thread-run2-noit ./sync/mutual_exclusion/synchronized_value/swap_T_pass.cpp : synchronized_value__swap_T_p ]
           [ thread-run2-noit ./sync/mutual_exclusion/synchronized_value/synchronize_pass.cpp : synchronized_value__synchronize_p ]
+ [ thread-run2-noit ./sync/mutual_exclusion/synchronized_value/call_pass.cpp : synchronized_value__call_p ]
 
     ;
 
@@ -789,7 +790,8 @@
           #[ thread-run test_8586.cpp ]
           #[ thread-run test_8596.cpp ]
           #[ thread-run test_8600.cpp ]
- #[ thread-run2-noit ./sync/mutual_exclusion/sync_bounded_queue/multi_thread_pass.cpp : sync_bounded_queue__multi_thread_p ]
+ #[ thread-run test_8943.cpp ]
+ #[ thread-run test_8960.cpp ]
           
     ;
 

Added: trunk/libs/thread/test/sync/mutual_exclusion/synchronized_value/call_pass.cpp
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ trunk/libs/thread/test/sync/mutual_exclusion/synchronized_value/call_pass.cpp 2013-08-11 16:33:47 EDT (Sun, 11 Aug 2013) (r85306)
@@ -0,0 +1,144 @@
+// Copyright (C) 2013 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)
+
+// <boost/thread/synchronized_value.hpp>
+
+// class synchronized_value<T,M>
+
+// template <typename F>
+// inline typename boost::result_of<F(value_type&)>::type
+// operator()(BOOST_THREAD_RV_REF(F) fct);
+// template <typename F>
+// inline typename boost::result_of<F(value_type const&)>::type
+// operator()(BOOST_THREAD_RV_REF(F) fct) const;
+
+#include <boost/config.hpp>
+#if ! defined BOOST_NO_CXX11_DECLTYPE
+#define BOOST_RESULT_OF_USE_DECLTYPE
+#endif
+
+#define BOOST_THREAD_VERSION 4
+
+#include <boost/thread/synchronized_value.hpp>
+
+#include <boost/detail/lightweight_test.hpp>
+
+struct S {
+ int f() const {return 1;}
+ int g() {return 1;}
+};
+
+void c(S const& s)
+{
+ BOOST_TEST(s.f()==1);
+}
+
+void nc(S & s)
+{
+ BOOST_TEST(s.f()==1);
+ BOOST_TEST(s.g()==1);
+}
+
+struct cfctr {
+ typedef void result_type;
+ void operator()(S const& s) const {
+ BOOST_TEST(s.f()==1);
+ }
+};
+struct ncfctr {
+ typedef void result_type;
+ void operator()(S& s) const {
+ BOOST_TEST(s.f()==1);
+ BOOST_TEST(s.g()==1);
+ }
+};
+
+struct cfctr3 {
+ typedef void result_type;
+ BOOST_THREAD_MOVABLE_ONLY(cfctr3)
+ cfctr3()
+ {}
+ cfctr3(BOOST_THREAD_RV_REF(cfctr3))
+ {}
+ void operator()(S const& s) const {
+ BOOST_TEST(s.f()==1);
+ }
+};
+struct ncfctr3 {
+ typedef void result_type;
+ BOOST_THREAD_MOVABLE_ONLY(ncfctr3)
+ ncfctr3()
+ {}
+ ncfctr3(BOOST_THREAD_RV_REF(ncfctr3))
+ {}
+ void operator()(S& s) const {
+ BOOST_TEST(s.f()==1);
+ BOOST_TEST(s.g()==1);
+ }
+};
+
+cfctr3 make_cfctr3() {
+ return BOOST_THREAD_MAKE_RV_REF(cfctr3());
+}
+
+ncfctr3 make_ncfctr3() {
+ return BOOST_THREAD_MAKE_RV_REF(ncfctr3());
+}
+
+int main()
+{
+ {
+ boost::synchronized_value<S> v;
+ v(&nc);
+ //v(&c);
+ }
+ {
+ const boost::synchronized_value<S> v;
+ v(&c);
+ }
+ {
+ boost::synchronized_value<S> v;
+ v(ncfctr());
+ }
+ {
+ const boost::synchronized_value<S> v;
+ v(cfctr());
+ }
+ {
+ boost::synchronized_value<S> v;
+ ncfctr fct;
+ v(fct);
+ }
+ {
+ const boost::synchronized_value<S> v;
+ cfctr fct;
+ v(fct);
+ }
+ {
+ boost::synchronized_value<S> v;
+ v(make_ncfctr3());
+ }
+ {
+ const boost::synchronized_value<S> v;
+ v(make_cfctr3());
+ }
+#if ! defined BOOST_NO_CXX11_LAMBDAS
+ {
+ boost::synchronized_value<S> v;
+ v([](S& s) {
+ BOOST_TEST(s.f()==1);
+ BOOST_TEST(s.g()==1);
+ });
+ }
+ {
+ const boost::synchronized_value<S> v;
+ v([](S const& s) {
+ BOOST_TEST(s.f()==1);
+ });
+ }
+#endif
+ return boost::report_errors();
+}
+


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk