]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/interprocess/test/condition_test_template.hpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / libs / interprocess / test / condition_test_template.hpp
CommitLineData
7c673cae
FG
1// Copyright (C) 2001-2003
2// William E. Kempf
3//
4// Permission to use, copy, modify, distribute and sell this software
5// and its documentation for any purpose is hereby granted without fee,
6// provided that the above copyright notice appear in all copies and
7// that both that copyright notice and this permission notice appear
8// in supporting documentation. William E. Kempf makes no representations
9// about the suitability of this software for any purpose.
10// It is provided "as is" without express or implied warranty.
11//////////////////////////////////////////////////////////////////////////////
12//
13// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
14// Software License, Version 1.0. (See accompanying file
15// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
16//
17// See http://www.boost.org/libs/interprocess for documentation.
18//
19//////////////////////////////////////////////////////////////////////////////
20#ifndef BOOST_INTERPROCESS_CONDITION_TEST_TEMPLATE_HPP
21#define BOOST_INTERPROCESS_CONDITION_TEST_TEMPLATE_HPP
22
23#include <boost/interprocess/detail/config_begin.hpp>
24#include <boost/interprocess/detail/workaround.hpp>
25#include <boost/interprocess/detail/os_thread_functions.hpp>
26#include "boost_interprocess_check.hpp"
27#include <boost/interprocess/sync/scoped_lock.hpp>
1e59de90 28#include "util.hpp"
7c673cae
FG
29#include <iostream>
30
31namespace boost{
32namespace interprocess{
33namespace test {
34
7c673cae
FG
35template <typename F, typename T>
36class binder
37{
38public:
39 binder(const F& f, const T& p)
40 : func(f), param(p) { }
41 void operator()() const { func(param); }
42
43private:
44 F func;
45 T param;
46};
47
48template <typename F, typename T>
49binder<F, T> bind_function(F func, T param)
50{
51 return binder<F, T>(func, param);
52}
53
54template <class Condition, class Mutex>
55struct condition_test_data
56{
57 condition_test_data() : notified(0), awoken(0) { }
58
59 ~condition_test_data()
60 {}
61
62 Mutex mutex;
63 Condition condition;
64 int notified;
65 int awoken;
66};
67
68template <class Condition, class Mutex>
69void condition_test_thread(condition_test_data<Condition, Mutex>* data)
70{
71 boost::interprocess::scoped_lock<Mutex>
72 lock(data->mutex);
73 BOOST_INTERPROCESS_CHECK(lock ? true : false);
74 while (!(data->notified > 0))
75 data->condition.wait(lock);
76 BOOST_INTERPROCESS_CHECK(lock ? true : false);
77 data->awoken++;
78}
79
80struct cond_predicate
81{
82 cond_predicate(int& var, int val) : _var(var), _val(val) { }
83
84 bool operator()() { return _var == _val; }
85
86 int& _var;
87 int _val;
88};
89
7c673cae 90
7c673cae
FG
91
92template <class Condition, class Mutex>
93void do_test_condition_notify_one()
94{
95 condition_test_data<Condition, Mutex> data;
96
97 boost::interprocess::ipcdetail::OS_thread_t thread;
98 boost::interprocess::ipcdetail::thread_launch(thread, bind_function(&condition_test_thread<Condition, Mutex>, &data));
99 //Make sure thread is blocked
100 boost::interprocess::ipcdetail::thread_sleep(1000);
101 {
102 boost::interprocess::scoped_lock<Mutex>
103 lock(data.mutex);
104 BOOST_INTERPROCESS_CHECK(lock ? true : false);
105 data.notified++;
106 data.condition.notify_one();
107 }
108
109 boost::interprocess::ipcdetail::thread_join(thread);
110 BOOST_INTERPROCESS_CHECK(data.awoken == 1);
111}
112
113template <class Condition, class Mutex>
114void do_test_condition_notify_all()
115{
116 const int NUMTHREADS = 3;
117
1e59de90 118 boost::interprocess::ipcdetail::OS_thread_t thgroup[std::size_t(NUMTHREADS)];
7c673cae
FG
119 condition_test_data<Condition, Mutex> data;
120
121 for(int i = 0; i< NUMTHREADS; ++i){
122 boost::interprocess::ipcdetail::thread_launch(thgroup[i], bind_function(&condition_test_thread<Condition, Mutex>, &data));
123 }
124
125 //Make sure all threads are blocked
126 boost::interprocess::ipcdetail::thread_sleep(1000);
127 {
128 boost::interprocess::scoped_lock<Mutex>
129 lock(data.mutex);
130 BOOST_INTERPROCESS_CHECK(lock ? true : false);
131 data.notified++;
132 }
133 data.condition.notify_all();
134
135 for(int i = 0; i< NUMTHREADS; ++i){
136 boost::interprocess::ipcdetail::thread_join(thgroup[i]);
137 }
138 BOOST_INTERPROCESS_CHECK(data.awoken == NUMTHREADS);
139}
140
1e59de90
TL
141template <class Condition, class Mutex>
142void do_test_condition_waits_step( condition_test_data<Condition, Mutex> &data
143 , boost::interprocess::scoped_lock<Mutex> &lock
144 , int awoken)
145{
146 boost::interprocess::ipcdetail::thread_sleep(1000);
147 data.notified++;
148 data.condition.notify_one();
149 while (data.awoken != awoken)
150 data.condition.wait(lock);
151 BOOST_INTERPROCESS_CHECK(lock ? true : false);
152 BOOST_INTERPROCESS_CHECK(data.awoken == awoken);
153}
154
155template <class Condition, class Mutex>
156void condition_test_waits(condition_test_data<Condition, Mutex>* data)
157{
158 boost::interprocess::scoped_lock<Mutex>
159 lock(data->mutex);
160 BOOST_INTERPROCESS_CHECK(lock ? true : false);
161
162 // Test wait.
163 while (data->notified != 1)
164 data->condition.wait(lock);
165 BOOST_INTERPROCESS_CHECK(lock ? true : false);
166 BOOST_INTERPROCESS_CHECK(data->notified == 1);
167 data->awoken++;
168 data->condition.notify_one();
169
170 // Test predicate wait.
171 data->condition.wait(lock, cond_predicate(data->notified, 2));
172 BOOST_INTERPROCESS_CHECK(lock ? true : false);
173 BOOST_INTERPROCESS_CHECK(data->notified == 2);
174 data->awoken++;
175 data->condition.notify_one();
176
177 // Test timed_wait
178 while (data->notified != 3)
179 data->condition.timed_wait(lock, ptime_delay(5));
180 BOOST_INTERPROCESS_CHECK(lock ? true : false);
181 BOOST_INTERPROCESS_CHECK(data->notified == 3);
182 data->awoken++;
183 data->condition.notify_one();
184
185 // Test predicate timed_wait.
186 {
187 bool ret = data->condition.timed_wait(lock, boost_systemclock_delay(5), cond_predicate (data->notified, 4));
188 BOOST_INTERPROCESS_CHECK(ret);(void)ret;
189 BOOST_INTERPROCESS_CHECK(lock ? true : false);
190 BOOST_INTERPROCESS_CHECK(data->notified == 4);
191 data->awoken++;
192 data->condition.notify_one();
193 }
194
195 // Test timed_wait
196 while (data->notified != 5)
197 data->condition.timed_wait(lock, std_systemclock_delay(5));
198 BOOST_INTERPROCESS_CHECK(lock ? true : false);
199 BOOST_INTERPROCESS_CHECK(data->notified == 5);
200 data->awoken++;
201 data->condition.notify_one();
202
203 // Test wait_until
204 while (data->notified != 6)
205 data->condition.wait_until(lock, ptime_delay(5));
206 BOOST_INTERPROCESS_CHECK(lock ? true : false);
207 BOOST_INTERPROCESS_CHECK(data->notified == 6);
208 data->awoken++;
209 data->condition.notify_one();
210
211 // Test predicate wait_until.
212 {
213 bool ret = data->condition.wait_until(lock, boost_systemclock_delay(5), cond_predicate (data->notified, 7));
214 BOOST_INTERPROCESS_CHECK(ret);(void)ret;
215 BOOST_INTERPROCESS_CHECK(lock ? true : false);
216 BOOST_INTERPROCESS_CHECK(data->notified == 7);
217 data->awoken++;
218 data->condition.notify_one();
219 }
220
221 // Test wait_for
222 while (data->notified != 8)
223 data->condition.wait_for(lock, ptime_seconds(5));
224 BOOST_INTERPROCESS_CHECK(lock ? true : false);
225 BOOST_INTERPROCESS_CHECK(data->notified == 8);
226 data->awoken++;
227 data->condition.notify_one();
228
229 // Test predicate wait_for.
230 {
231 bool ret = data->condition.wait_for(lock, ptime_seconds(5), cond_predicate (data->notified, 9));
232 BOOST_INTERPROCESS_CHECK(ret);(void)ret;
233 BOOST_INTERPROCESS_CHECK(lock ? true : false);
234 BOOST_INTERPROCESS_CHECK(data->notified == 9);
235 data->awoken++;
236 data->condition.notify_one();
237 }
238
239 // Test wait_for
240 while (data->notified != 10)
241 data->condition.wait_for(lock, boost_systemclock_seconds(5));
242 BOOST_INTERPROCESS_CHECK(lock ? true : false);
243 BOOST_INTERPROCESS_CHECK(data->notified == 10);
244 data->awoken++;
245 data->condition.notify_one();
246
247 // Test predicate wait_for.
248 {
249 bool ret = data->condition.wait_for(lock, boost_systemclock_seconds(5), cond_predicate (data->notified, 11));
250 BOOST_INTERPROCESS_CHECK(ret);(void)ret;
251 BOOST_INTERPROCESS_CHECK(lock ? true : false);
252 BOOST_INTERPROCESS_CHECK(data->notified == 11);
253 data->awoken++;
254 data->condition.notify_one();
255 }
256
257 // Test wait_for
258 while (data->notified != 12)
259 data->condition.wait_for(lock, std_systemclock_seconds(5));
260 BOOST_INTERPROCESS_CHECK(lock ? true : false);
261 BOOST_INTERPROCESS_CHECK(data->notified == 12);
262 data->awoken++;
263 data->condition.notify_one();
264
265 // Test predicate wait_for.
266 {
267 bool ret = data->condition.wait_for(lock, std_systemclock_seconds(5), cond_predicate (data->notified, 13));
268 BOOST_INTERPROCESS_CHECK(ret);(void)ret;
269 BOOST_INTERPROCESS_CHECK(lock ? true : false);
270 BOOST_INTERPROCESS_CHECK(data->notified == 13);
271 data->awoken++;
272 data->condition.notify_one();
273 }
274}
275
7c673cae
FG
276template <class Condition, class Mutex>
277void do_test_condition_waits()
278{
279 condition_test_data<Condition, Mutex> data;
280 boost::interprocess::ipcdetail::OS_thread_t thread;
281 boost::interprocess::ipcdetail::thread_launch(thread, bind_function(&condition_test_waits<Condition, Mutex>, &data));
282
283 {
284 boost::interprocess::scoped_lock<Mutex>
285 lock(data.mutex);
286 BOOST_INTERPROCESS_CHECK(lock ? true : false);
287
1e59de90
TL
288 for(int i = 1; i <= 13; ++i)
289 do_test_condition_waits_step(data, lock, i);
7c673cae
FG
290 }
291
292 boost::interprocess::ipcdetail::thread_join(thread);
1e59de90 293 BOOST_INTERPROCESS_CHECK(data.awoken == 13);
7c673cae 294}
1e59de90 295
7c673cae
FG
296/*
297//Message queue simulation test
298template <class Condition>
299inline Condition &cond_empty()
300{
301 static Condition cond_empty;
302 return cond_empty;
303}
304
305template <class Condition>
306inline Condition &cond_full()
307{
308 static Condition cond_full;
309 return cond_full;
310}
311
312
313template <class Mutex>
314inline Mutex &mutex()
315{
316 static Mutex mut;
317 return mut;
318}
319*/
1e59de90
TL
320static int count = 0;
321static int waiting_readers = 0;
322static int waiting_writer = 0;
7c673cae
FG
323const int queue_size = 3;
324const int thread_factor = 10;
325const int NumThreads = thread_factor*queue_size;
326
327//Function that removes items from queue
328template <class Condition, class Mutex>
329struct condition_func
330{
331 condition_func(Condition &cond_full, Condition &cond_empty, Mutex &mutex)
332 : cond_full_(cond_full), cond_empty_(cond_empty), mutex_(mutex)
333 {}
334
335 void operator()()
336 {
337 boost::interprocess::scoped_lock<Mutex>lock(mutex_);
338 while(count == 0){
339 ++waiting_readers;
340 cond_empty_.wait(lock);
341 --waiting_readers;
342 }
343 --count;
344 if(waiting_writer)
345 cond_full_.notify_one();
346 }
347 Condition &cond_full_;
348 Condition &cond_empty_;
349 Mutex &mutex_;
350};
351
352//Queue functions
353template <class Condition, class Mutex>
354void do_test_condition_queue_notify_one(void)
355{
356 //Force mutex and condition creation
357 Condition cond_empty;
358 Condition cond_full;
359 Mutex mutex;
360
361 //Create threads that will decrease count
362 {
363 //Initialize counters
364 count = 0;
365 waiting_readers = 0;
366 waiting_writer = 0;
367
1e59de90 368 boost::interprocess::ipcdetail::OS_thread_t thgroup[std::size_t(NumThreads)];
7c673cae
FG
369 for(int i = 0; i< NumThreads; ++i){
370 condition_func<Condition, Mutex> func(cond_full, cond_empty, mutex);
371 boost::interprocess::ipcdetail::thread_launch(thgroup[i], func);
372 }
373
374 //Add 20 elements one by one in the queue simulation
375 //The sender will block if it fills the queue
376 for(int i = 0; i < NumThreads; ++i){
377 boost::interprocess::scoped_lock<Mutex> lock(mutex);
378 while(count == queue_size){
379 ++waiting_writer;
380 cond_full.wait(lock);
381 --waiting_writer;
382 }
383 count++;
384
385 if(waiting_readers)
386 cond_empty.notify_one();
387 }
388 for(int i = 0; i< NumThreads; ++i){
389 boost::interprocess::ipcdetail::thread_join(thgroup[i]);
390 }
391 BOOST_INTERPROCESS_CHECK(count == 0);
392 BOOST_INTERPROCESS_CHECK(waiting_readers == 0);
393 BOOST_INTERPROCESS_CHECK(waiting_writer == 0);
394 }
395}
396
397//Queue functions
398template <class Condition, class Mutex>
399void do_test_condition_queue_notify_all(void)
400{
401 //Force mutex and condition creation
402 Condition cond_empty;
403 Condition cond_full;
404 Mutex mutex;
405
406 //Create threads that will decrease count
407 {
408 //Initialize counters
409 count = 0;
410 waiting_readers = 0;
411 waiting_writer = 0;
412
1e59de90 413 boost::interprocess::ipcdetail::OS_thread_t thgroup[std::size_t(NumThreads)];
7c673cae
FG
414 for(int i = 0; i< NumThreads; ++i){
415 condition_func<Condition, Mutex> func(cond_full, cond_empty, mutex);
416 boost::interprocess::ipcdetail::thread_launch(thgroup[i], func);
417 }
418
419 //Fill queue to the max size and notify all several times
420 for(int i = 0; i < NumThreads; ++i){
421 boost::interprocess::scoped_lock<Mutex>lock(mutex);
422 while(count == queue_size){
423 ++waiting_writer;
424 cond_full.wait(lock);
425 --waiting_writer;
426 }
427 count++;
428
429 if(waiting_readers)
430 cond_empty.notify_all();
431 }
432 for(int i = 0; i< NumThreads; ++i){
433 boost::interprocess::ipcdetail::thread_join(thgroup[i]);
434 }
435 BOOST_INTERPROCESS_CHECK(count == 0);
436 BOOST_INTERPROCESS_CHECK(waiting_readers == 0);
437 BOOST_INTERPROCESS_CHECK(waiting_writer == 0);
438 }
439}
440
441template <class Condition, class Mutex>
442bool do_test_condition()
443{
444 std::cout << "do_test_condition_notify_one<" << typeid(Condition).name() << "," << typeid(Mutex).name() << '\n' << std::endl;
445 do_test_condition_notify_one<Condition, Mutex>();
446 std::cout << "do_test_condition_notify_all<" << typeid(Condition).name() << "," << typeid(Mutex).name() << '\n' << std::endl;
447 do_test_condition_notify_all<Condition, Mutex>();
448 std::cout << "do_test_condition_waits<" << typeid(Condition).name() << "," << typeid(Mutex).name() << '\n' << std::endl;
449 do_test_condition_waits<Condition, Mutex>();
450 std::cout << "do_test_condition_queue_notify_one<" << typeid(Condition).name() << "," << typeid(Mutex).name() << '\n' << std::endl;
451 do_test_condition_queue_notify_one<Condition, Mutex>();
452 std::cout << "do_test_condition_queue_notify_all<" << typeid(Condition).name() << "," << typeid(Mutex).name() << '\n' << std::endl;
453 do_test_condition_queue_notify_all<Condition, Mutex>();
454 return true;
455}
456
457} //namespace test
458} //namespace interprocess{
459} //namespace boost{
460
461#include <boost/interprocess/detail/config_end.hpp>
462
463#endif //#ifndef BOOST_INTERPROCESS_CONDITION_TEST_TEMPLATE_HPP