• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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