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