// Copyright (C) 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) #include #include #include #include #include #if defined BOOST_THREAD_DONT_USE_CHRONO #include #endif #include #include #define EXCLUSIVE 1 #define SHARED 2 #define MODE SHARED class A { #if MODE == EXCLUSIVE typedef boost::mutex mutex_type; #elif MODE == SHARED typedef boost::shared_mutex mutex_type; #else #error MODE not set #endif typedef std::vector C; mutable mutex_type mut_; C data_; public: A() : data_(10000000) {} A(const A& a); A& operator=(const A& a); void compute(const A& x, const A& y); }; A::A(const A& a) { #if MODE == EXCLUSIVE boost::unique_lock lk(a.mut_); #elif MODE == SHARED boost::shared_lock lk(a.mut_); #else #error MODE not set #endif data_ = a.data_; } A& A::operator=(const A& a) { if (this != &a) { boost::unique_lock lk1(mut_, boost::defer_lock); #if MODE == EXCLUSIVE boost::unique_lock lk2(a.mut_, boost::defer_lock); #elif MODE == SHARED boost::shared_lock lk2(a.mut_, boost::defer_lock); #else #error MODE not set #endif boost::lock(lk1, lk2); data_ = a.data_; } return *this; } void A::compute(const A& x, const A& y) { boost::unique_lock lk1(mut_, boost::defer_lock); #if MODE == EXCLUSIVE boost::unique_lock lk2(x.mut_, boost::defer_lock); boost::unique_lock lk3(y.mut_, boost::defer_lock); #elif MODE == SHARED boost::shared_lock lk2(x.mut_, boost::defer_lock); boost::shared_lock lk3(y.mut_, boost::defer_lock); #else #error MODE not set #endif boost::lock(lk1, lk2, lk3); assert(data_.size() == x.data_.size()); assert(data_.size() == y.data_.size()); for (unsigned i = 0; i < data_.size(); ++i) data_[i] = (x.data_[i] + y.data_[i]) / 2; } A a1; A a2; void test_s() { A la3 = a1; for (int i = 0; i < 150; ++i) { la3.compute(a1, a2); } } void test_w() { A la3 = a1; for (int i = 0; i < 10; ++i) { la3.compute(a1, a2); a1 = la3; a2 = la3; #if defined BOOST_THREAD_DONT_USE_CHRONO boost::this_thread::sleep_for(boost::chrono::seconds(1)); #endif } } int main() { #if defined BOOST_THREAD_DONT_USE_CHRONO typedef boost::chrono::high_resolution_clock Clock; typedef boost::chrono::duration sec; Clock::time_point t0 = Clock::now(); #endif std::vector v; boost::thread thw(test_w); v.push_back(&thw); boost::thread thr0(test_w); v.push_back(&thr0); boost::thread thr1(test_w); v.push_back(&thr1); boost::thread thr2(test_w); v.push_back(&thr2); boost::thread thr3(test_w); v.push_back(&thr3); for (std::size_t i = 0; i < v.size(); ++i) v[i]->join(); #if defined BOOST_THREAD_DONT_USE_CHRONO Clock::time_point t1 = Clock::now(); std::cout << sec(t1-t0) << '\n'; #endif return 0; }