1 #ifndef SHARED_MUTEX_LOCKING_THREAD_HPP
2 #define SHARED_MUTEX_LOCKING_THREAD_HPP
3 
4 //  (C) Copyright 2008 Anthony Williams
5 //
6 //  Distributed under the Boost Software License, Version 1.0. (See
7 //  accompanying file LICENSE_1_0.txt or copy at
8 //  http://www.boost.org/LICENSE_1_0.txt)
9 
10 #include <boost/config.hpp>
11 #include <boost/thread/mutex.hpp>
12 #include <boost/thread/condition_variable.hpp>
13 #include <boost/thread/shared_mutex.hpp>
14 
15 template<typename lock_type>
16 class locking_thread
17 {
18     boost::shared_mutex& rw_mutex;
19     unsigned& unblocked_count;
20     boost::condition_variable& unblocked_condition;
21     unsigned& simultaneous_running_count;
22     unsigned& max_simultaneous_running;
23     boost::mutex& unblocked_count_mutex;
24     boost::mutex& finish_mutex;
25 public:
locking_thread(boost::shared_mutex & rw_mutex_,unsigned & unblocked_count_,boost::mutex & unblocked_count_mutex_,boost::condition_variable & unblocked_condition_,boost::mutex & finish_mutex_,unsigned & simultaneous_running_count_,unsigned & max_simultaneous_running_)26     locking_thread(boost::shared_mutex& rw_mutex_,
27                    unsigned& unblocked_count_,
28                    boost::mutex& unblocked_count_mutex_,
29                    boost::condition_variable& unblocked_condition_,
30                    boost::mutex& finish_mutex_,
31                    unsigned& simultaneous_running_count_,
32                    unsigned& max_simultaneous_running_):
33         rw_mutex(rw_mutex_),
34         unblocked_count(unblocked_count_),
35         unblocked_condition(unblocked_condition_),
36         simultaneous_running_count(simultaneous_running_count_),
37         max_simultaneous_running(max_simultaneous_running_),
38         unblocked_count_mutex(unblocked_count_mutex_),
39         finish_mutex(finish_mutex_)
40     {}
41 
42 #if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS)
43     locking_thread(locking_thread const&) = default;
44 #endif
45 
operator ()()46     void operator()()
47     {
48         // acquire lock
49         lock_type lock(rw_mutex);
50 
51         // increment count to show we're unblocked
52         {
53             boost::unique_lock<boost::mutex> ublock(unblocked_count_mutex);
54             ++unblocked_count;
55             unblocked_condition.notify_one();
56             ++simultaneous_running_count;
57             if(simultaneous_running_count>max_simultaneous_running)
58             {
59                 max_simultaneous_running=simultaneous_running_count;
60             }
61         }
62 
63         // wait to finish
64         boost::unique_lock<boost::mutex> finish_lock(finish_mutex);
65         {
66             boost::unique_lock<boost::mutex> ublock(unblocked_count_mutex);
67             --simultaneous_running_count;
68         }
69     }
70 private:
71     void operator=(locking_thread&);
72 };
73 
74 class simple_writing_thread
75 {
76     boost::shared_mutex& rwm;
77     boost::mutex& finish_mutex;
78     boost::mutex& unblocked_mutex;
79     unsigned& unblocked_count;
80 
81     void operator=(simple_writing_thread&);
82 
83 public:
simple_writing_thread(boost::shared_mutex & rwm_,boost::mutex & finish_mutex_,boost::mutex & unblocked_mutex_,unsigned & unblocked_count_)84     simple_writing_thread(boost::shared_mutex& rwm_,
85                           boost::mutex& finish_mutex_,
86                           boost::mutex& unblocked_mutex_,
87                           unsigned& unblocked_count_):
88         rwm(rwm_),finish_mutex(finish_mutex_),
89         unblocked_mutex(unblocked_mutex_),unblocked_count(unblocked_count_)
90     {}
91 
92 #if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS)
93     simple_writing_thread(simple_writing_thread const&) = default;
94 #endif
95 
operator ()()96     void operator()()
97     {
98         boost::unique_lock<boost::shared_mutex>  lk(rwm);
99 
100         {
101             boost::unique_lock<boost::mutex> ulk(unblocked_mutex);
102             ++unblocked_count;
103         }
104 
105         boost::unique_lock<boost::mutex> flk(finish_mutex);
106     }
107 };
108 
109 class simple_reading_thread
110 {
111     boost::shared_mutex& rwm;
112     boost::mutex& finish_mutex;
113     boost::mutex& unblocked_mutex;
114     unsigned& unblocked_count;
115 
116     void operator=(simple_reading_thread&);
117 
118 public:
simple_reading_thread(boost::shared_mutex & rwm_,boost::mutex & finish_mutex_,boost::mutex & unblocked_mutex_,unsigned & unblocked_count_)119     simple_reading_thread(boost::shared_mutex& rwm_,
120                           boost::mutex& finish_mutex_,
121                           boost::mutex& unblocked_mutex_,
122                           unsigned& unblocked_count_):
123         rwm(rwm_),finish_mutex(finish_mutex_),
124         unblocked_mutex(unblocked_mutex_),unblocked_count(unblocked_count_)
125     {}
126 
127 #if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS)
128     simple_reading_thread(simple_reading_thread const&) = default;
129 #endif
130 
operator ()()131     void operator()()
132     {
133         boost::shared_lock<boost::shared_mutex>  lk(rwm);
134 
135         {
136             boost::unique_lock<boost::mutex> ulk(unblocked_mutex);
137             ++unblocked_count;
138         }
139 
140         boost::unique_lock<boost::mutex> flk(finish_mutex);
141     }
142 };
143 
144 
145 #endif
146