1 // Copyright (C) 2012 Vicente J. Botet Escriba
2 //
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5
6 #include <iostream>
7 #include <boost/thread/mutex.hpp>
8 #include <boost/thread/shared_mutex.hpp>
9 #include <boost/thread/lock_algorithms.hpp>
10 #include <boost/thread/thread_only.hpp>
11 #if defined BOOST_THREAD_DONT_USE_CHRONO
12 #include <boost/chrono/chrono_io.hpp>
13 #endif
14 #include <cassert>
15 #include <vector>
16
17 #define EXCLUSIVE 1
18 #define SHARED 2
19
20 #define MODE SHARED
21
22 class A
23 {
24 #if MODE == EXCLUSIVE
25 typedef boost::mutex mutex_type;
26 #elif MODE == SHARED
27 typedef boost::shared_mutex mutex_type;
28 #else
29 #error MODE not set
30 #endif
31 typedef std::vector<double> C;
32 mutable mutex_type mut_;
33 C data_;
34 public:
A()35 A() : data_(10000000) {}
36 A(const A& a);
37 A& operator=(const A& a);
38
39 void compute(const A& x, const A& y);
40 };
41
A(const A & a)42 A::A(const A& a)
43 {
44 #if MODE == EXCLUSIVE
45 boost::unique_lock<mutex_type> lk(a.mut_);
46 #elif MODE == SHARED
47 boost::shared_lock<mutex_type> lk(a.mut_);
48 #else
49 #error MODE not set
50 #endif
51 data_ = a.data_;
52 }
53
54 A&
operator =(const A & a)55 A::operator=(const A& a)
56 {
57 if (this != &a)
58 {
59 boost::unique_lock<mutex_type> lk1(mut_, boost::defer_lock);
60 #if MODE == EXCLUSIVE
61 boost::unique_lock<mutex_type> lk2(a.mut_, boost::defer_lock);
62 #elif MODE == SHARED
63 boost::shared_lock<mutex_type> lk2(a.mut_, boost::defer_lock);
64 #else
65 #error MODE not set
66 #endif
67 boost::lock(lk1, lk2);
68 data_ = a.data_;
69 }
70 return *this;
71 }
72
73 void
compute(const A & x,const A & y)74 A::compute(const A& x, const A& y)
75 {
76 boost::unique_lock<mutex_type> lk1(mut_, boost::defer_lock);
77 #if MODE == EXCLUSIVE
78 boost::unique_lock<mutex_type> lk2(x.mut_, boost::defer_lock);
79 boost::unique_lock<mutex_type> lk3(y.mut_, boost::defer_lock);
80 #elif MODE == SHARED
81 boost::shared_lock<mutex_type> lk2(x.mut_, boost::defer_lock);
82 boost::shared_lock<mutex_type> lk3(y.mut_, boost::defer_lock);
83 #else
84 #error MODE not set
85 #endif
86 boost::lock(lk1, lk2, lk3);
87 assert(data_.size() == x.data_.size());
88 assert(data_.size() == y.data_.size());
89 for (unsigned i = 0; i < data_.size(); ++i)
90 data_[i] = (x.data_[i] + y.data_[i]) / 2;
91 }
92
93 A a1;
94 A a2;
95
test_s()96 void test_s()
97 {
98 A la3 = a1;
99 for (int i = 0; i < 150; ++i)
100 {
101 la3.compute(a1, a2);
102 }
103 }
104
test_w()105 void test_w()
106 {
107 A la3 = a1;
108 for (int i = 0; i < 10; ++i)
109 {
110 la3.compute(a1, a2);
111 a1 = la3;
112 a2 = la3;
113 #if defined BOOST_THREAD_DONT_USE_CHRONO
114 boost::this_thread::sleep_for(boost::chrono::seconds(1));
115 #endif
116 }
117 }
118
main()119 int main()
120 {
121 #if defined BOOST_THREAD_DONT_USE_CHRONO
122 typedef boost::chrono::high_resolution_clock Clock;
123 typedef boost::chrono::duration<double> sec;
124 Clock::time_point t0 = Clock::now();
125 #endif
126 std::vector<boost::thread*> v;
127 boost::thread thw(test_w);
128 v.push_back(&thw);
129 boost::thread thr0(test_w);
130 v.push_back(&thr0);
131 boost::thread thr1(test_w);
132 v.push_back(&thr1);
133 boost::thread thr2(test_w);
134 v.push_back(&thr2);
135 boost::thread thr3(test_w);
136 v.push_back(&thr3);
137 for (std::size_t i = 0; i < v.size(); ++i)
138 v[i]->join();
139 #if defined BOOST_THREAD_DONT_USE_CHRONO
140 Clock::time_point t1 = Clock::now();
141 std::cout << sec(t1-t0) << '\n';
142 #endif
143 return 0;
144 }
145