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
22class 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_;
34public:
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
42A::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
54A&
55A::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(m1&: lk1, m2&: lk2);
68 data_ = a.data_;
69 }
70 return *this;
71}
72
73void
74A::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(m1&: lk1, m2&: lk2, m3&: 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
93A a1;
94A a2;
95
96void test_s()
97{
98 A la3 = a1;
99 for (int i = 0; i < 150; ++i)
100 {
101 la3.compute(x: a1, y: a2);
102 }
103}
104
105void test_w()
106{
107 A la3 = a1;
108 for (int i = 0; i < 10; ++i)
109 {
110 la3.compute(x: a1, y: 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
119int 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(x: &thw);
129 boost::thread thr0(test_w);
130 v.push_back(x: &thr0);
131 boost::thread thr1(test_w);
132 v.push_back(x: &thr1);
133 boost::thread thr2(test_w);
134 v.push_back(x: &thr2);
135 boost::thread thr3(test_w);
136 v.push_back(x: &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

source code of boost/libs/thread/example/shared_monitor.cpp