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 | #define BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS |
7 | #define BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION |
8 | #define BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN |
9 | |
10 | #include <iostream> |
11 | #include <boost/thread/mutex.hpp> |
12 | #include <boost/thread/shared_mutex.hpp> |
13 | #include <boost/thread/lock_algorithms.hpp> |
14 | #include <boost/thread/thread_only.hpp> |
15 | #include <vector> |
16 | |
17 | #if defined BOOST_THREAD_USES_CHRONO |
18 | #include <boost/chrono/chrono_io.hpp> |
19 | |
20 | |
21 | enum {reading, writing}; |
22 | int state = reading; |
23 | |
24 | #if 1 |
25 | |
26 | boost::mutex& |
27 | cout_mut() |
28 | { |
29 | static boost::mutex m; |
30 | return m; |
31 | } |
32 | |
33 | void |
34 | print(const char* tag, unsigned count, char ch) |
35 | { |
36 | boost::lock_guard<boost::mutex> _(cout_mut()); |
37 | std::cout << tag << count << ch; |
38 | } |
39 | |
40 | #elif 0 |
41 | |
42 | boost::recursive_mutex& |
43 | cout_mut() |
44 | { |
45 | static boost::recursive_mutex m; |
46 | return m; |
47 | } |
48 | |
49 | void print() {} |
50 | |
51 | template <class A0, class ...Args> |
52 | void |
53 | print(const A0& a0, const Args& ...args) |
54 | { |
55 | boost::lock_guard<boost::recursive_mutex> _(cout_mut()); |
56 | std::cout << a0; |
57 | print(args...); |
58 | } |
59 | |
60 | #else |
61 | |
62 | template <class A0, class A1, class A2> |
63 | void |
64 | print(const A0&, const A1& a1, const A2&) |
65 | { |
66 | assert(a1 > 10000); |
67 | } |
68 | |
69 | #endif |
70 | |
71 | namespace S |
72 | { |
73 | |
74 | boost::shared_mutex mut; |
75 | |
76 | void reader() |
77 | { |
78 | typedef boost::chrono::steady_clock Clock; |
79 | unsigned count = 0; |
80 | Clock::time_point until = Clock::now() + boost::chrono::seconds(3); |
81 | while (Clock::now() < until) |
82 | { |
83 | mut.lock_shared(); |
84 | assert(state == reading); |
85 | ++count; |
86 | mut.unlock_shared(); |
87 | } |
88 | print(tag: "reader = " , count, ch: '\n'); |
89 | } |
90 | |
91 | void writer() |
92 | { |
93 | typedef boost::chrono::steady_clock Clock; |
94 | unsigned count = 0; |
95 | Clock::time_point until = Clock::now() + boost::chrono::seconds(3); |
96 | while (Clock::now() < until) |
97 | { |
98 | mut.lock(); |
99 | state = writing; |
100 | assert(state == writing); |
101 | state = reading; |
102 | ++count; |
103 | mut.unlock(); |
104 | } |
105 | print(tag: "writer = " , count, ch: '\n'); |
106 | } |
107 | |
108 | void try_reader() |
109 | { |
110 | typedef boost::chrono::steady_clock Clock; |
111 | unsigned count = 0; |
112 | Clock::time_point until = Clock::now() + boost::chrono::seconds(3); |
113 | while (Clock::now() < until) |
114 | { |
115 | if (mut.try_lock_shared()) |
116 | { |
117 | assert(state == reading); |
118 | ++count; |
119 | mut.unlock_shared(); |
120 | } |
121 | } |
122 | print(tag: "try_reader = " , count, ch: '\n'); |
123 | } |
124 | |
125 | void try_writer() |
126 | { |
127 | typedef boost::chrono::steady_clock Clock; |
128 | unsigned count = 0; |
129 | Clock::time_point until = Clock::now() + boost::chrono::seconds(3); |
130 | while (Clock::now() < until) |
131 | { |
132 | if (mut.try_lock()) |
133 | { |
134 | state = writing; |
135 | assert(state == writing); |
136 | state = reading; |
137 | ++count; |
138 | mut.unlock(); |
139 | } |
140 | } |
141 | print(tag: "try_writer = " , count, ch: '\n'); |
142 | } |
143 | |
144 | void try_for_reader() |
145 | { |
146 | typedef boost::chrono::steady_clock Clock; |
147 | unsigned count = 0; |
148 | Clock::time_point until = Clock::now() + boost::chrono::seconds(3); |
149 | while (Clock::now() < until) |
150 | { |
151 | if (mut.try_lock_shared_for(rel_time: boost::chrono::microseconds(5))) |
152 | { |
153 | assert(state == reading); |
154 | ++count; |
155 | mut.unlock_shared(); |
156 | } |
157 | } |
158 | print(tag: "try_for_reader = " , count, ch: '\n'); |
159 | } |
160 | |
161 | void try_for_writer() |
162 | { |
163 | typedef boost::chrono::steady_clock Clock; |
164 | unsigned count = 0; |
165 | Clock::time_point until = Clock::now() + boost::chrono::seconds(3); |
166 | while (Clock::now() < until) |
167 | { |
168 | if (mut.try_lock_for(rel_time: boost::chrono::microseconds(5))) |
169 | { |
170 | state = writing; |
171 | assert(state == writing); |
172 | state = reading; |
173 | ++count; |
174 | mut.unlock(); |
175 | } |
176 | } |
177 | print(tag: "try_for_writer = " , count, ch: '\n'); |
178 | } |
179 | |
180 | void |
181 | test_shared_mutex() |
182 | { |
183 | std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl; |
184 | { |
185 | boost::thread t1(reader); |
186 | boost::thread t2(writer); |
187 | boost::thread t3(reader); |
188 | t1.join(); |
189 | t2.join(); |
190 | t3.join(); |
191 | } |
192 | std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl; |
193 | { |
194 | boost::thread t1(try_reader); |
195 | boost::thread t2(try_writer); |
196 | boost::thread t3(try_reader); |
197 | t1.join(); |
198 | t2.join(); |
199 | t3.join(); |
200 | } |
201 | std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl; |
202 | { |
203 | boost::thread t1(try_for_reader); |
204 | boost::thread t2(try_for_writer); |
205 | boost::thread t3(try_for_reader); |
206 | t1.join(); |
207 | t2.join(); |
208 | t3.join(); |
209 | } |
210 | std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl; |
211 | } |
212 | |
213 | } |
214 | |
215 | namespace U |
216 | { |
217 | |
218 | boost::upgrade_mutex mut; |
219 | |
220 | void reader() |
221 | { |
222 | typedef boost::chrono::steady_clock Clock; |
223 | unsigned count = 0; |
224 | Clock::time_point until = Clock::now() + boost::chrono::seconds(3); |
225 | while (Clock::now() < until) |
226 | { |
227 | mut.lock_shared(); |
228 | assert(state == reading); |
229 | ++count; |
230 | mut.unlock_shared(); |
231 | } |
232 | print(tag: "reader = " , count, ch: '\n'); |
233 | } |
234 | |
235 | void writer() |
236 | { |
237 | typedef boost::chrono::steady_clock Clock; |
238 | unsigned count = 0; |
239 | Clock::time_point until = Clock::now() + boost::chrono::seconds(3); |
240 | while (Clock::now() < until) |
241 | { |
242 | mut.lock(); |
243 | state = writing; |
244 | assert(state == writing); |
245 | state = reading; |
246 | ++count; |
247 | mut.unlock(); |
248 | } |
249 | print(tag: "writer = " , count, ch: '\n'); |
250 | } |
251 | |
252 | void try_reader() |
253 | { |
254 | typedef boost::chrono::steady_clock Clock; |
255 | unsigned count = 0; |
256 | Clock::time_point until = Clock::now() + boost::chrono::seconds(3); |
257 | while (Clock::now() < until) |
258 | { |
259 | if (mut.try_lock_shared()) |
260 | { |
261 | assert(state == reading); |
262 | ++count; |
263 | mut.unlock_shared(); |
264 | } |
265 | } |
266 | print(tag: "try_reader = " , count, ch: '\n'); |
267 | } |
268 | |
269 | void try_writer() |
270 | { |
271 | typedef boost::chrono::steady_clock Clock; |
272 | unsigned count = 0; |
273 | Clock::time_point until = Clock::now() + boost::chrono::seconds(3); |
274 | while (Clock::now() < until) |
275 | { |
276 | if (mut.try_lock()) |
277 | { |
278 | state = writing; |
279 | assert(state == writing); |
280 | state = reading; |
281 | ++count; |
282 | mut.unlock(); |
283 | } |
284 | } |
285 | print(tag: "try_writer = " , count, ch: '\n'); |
286 | } |
287 | |
288 | void try_for_reader() |
289 | { |
290 | typedef boost::chrono::steady_clock Clock; |
291 | unsigned count = 0; |
292 | Clock::time_point until = Clock::now() + boost::chrono::seconds(3); |
293 | while (Clock::now() < until) |
294 | { |
295 | if (mut.try_lock_shared_for(rel_time: boost::chrono::microseconds(5))) |
296 | { |
297 | assert(state == reading); |
298 | ++count; |
299 | mut.unlock_shared(); |
300 | } |
301 | } |
302 | print(tag: "try_for_reader = " , count, ch: '\n'); |
303 | } |
304 | |
305 | void try_for_writer() |
306 | { |
307 | typedef boost::chrono::steady_clock Clock; |
308 | unsigned count = 0; |
309 | Clock::time_point until = Clock::now() + boost::chrono::seconds(3); |
310 | while (Clock::now() < until) |
311 | { |
312 | if (mut.try_lock_for(rel_time: boost::chrono::microseconds(5))) |
313 | { |
314 | state = writing; |
315 | assert(state == writing); |
316 | state = reading; |
317 | ++count; |
318 | mut.unlock(); |
319 | } |
320 | } |
321 | print(tag: "try_for_writer = " , count, ch: '\n'); |
322 | } |
323 | |
324 | void upgradable() |
325 | { |
326 | typedef boost::chrono::steady_clock Clock; |
327 | unsigned count = 0; |
328 | Clock::time_point until = Clock::now() + boost::chrono::seconds(3); |
329 | while (Clock::now() < until) |
330 | { |
331 | mut.lock_upgrade(); |
332 | assert(state == reading); |
333 | ++count; |
334 | mut.unlock_upgrade(); |
335 | } |
336 | print(tag: "upgradable = " , count, ch: '\n'); |
337 | } |
338 | |
339 | void try_upgradable() |
340 | { |
341 | typedef boost::chrono::steady_clock Clock; |
342 | unsigned count = 0; |
343 | Clock::time_point until = Clock::now() + boost::chrono::seconds(3); |
344 | while (Clock::now() < until) |
345 | { |
346 | if (mut.try_lock_upgrade()) |
347 | { |
348 | assert(state == reading); |
349 | ++count; |
350 | mut.unlock_upgrade(); |
351 | } |
352 | } |
353 | print(tag: "try_upgradable = " , count, ch: '\n'); |
354 | } |
355 | |
356 | void try_for_upgradable() |
357 | { |
358 | typedef boost::chrono::steady_clock Clock; |
359 | unsigned count = 0; |
360 | Clock::time_point until = Clock::now() + boost::chrono::seconds(3); |
361 | while (Clock::now() < until) |
362 | { |
363 | if (mut.try_lock_upgrade_for(rel_time: boost::chrono::microseconds(5))) |
364 | { |
365 | assert(state == reading); |
366 | ++count; |
367 | mut.unlock_upgrade(); |
368 | } |
369 | } |
370 | print(tag: "try_for_upgradable = " , count, ch: '\n'); |
371 | } |
372 | |
373 | void clockwise() |
374 | { |
375 | typedef boost::chrono::steady_clock Clock; |
376 | unsigned count = 0; |
377 | Clock::time_point until = Clock::now() + boost::chrono::seconds(3); |
378 | while (Clock::now() < until) |
379 | { |
380 | mut.lock_shared(); |
381 | assert(state == reading); |
382 | if (mut.try_unlock_shared_and_lock()) |
383 | { |
384 | state = writing; |
385 | } |
386 | else if (mut.try_unlock_shared_and_lock_upgrade()) |
387 | { |
388 | assert(state == reading); |
389 | mut.unlock_upgrade_and_lock(); |
390 | state = writing; |
391 | } |
392 | else |
393 | { |
394 | mut.unlock_shared(); |
395 | continue; |
396 | } |
397 | assert(state == writing); |
398 | state = reading; |
399 | mut.unlock_and_lock_upgrade(); |
400 | assert(state == reading); |
401 | mut.unlock_upgrade_and_lock_shared(); |
402 | assert(state == reading); |
403 | mut.unlock_shared(); |
404 | ++count; |
405 | } |
406 | print(tag: "clockwise = " , count, ch: '\n'); |
407 | } |
408 | |
409 | void counter_clockwise() |
410 | { |
411 | typedef boost::chrono::steady_clock Clock; |
412 | unsigned count = 0; |
413 | Clock::time_point until = Clock::now() + boost::chrono::seconds(3); |
414 | while (Clock::now() < until) |
415 | { |
416 | mut.lock_upgrade(); |
417 | assert(state == reading); |
418 | mut.unlock_upgrade_and_lock(); |
419 | assert(state == reading); |
420 | state = writing; |
421 | assert(state == writing); |
422 | state = reading; |
423 | mut.unlock_and_lock_shared(); |
424 | assert(state == reading); |
425 | mut.unlock_shared(); |
426 | ++count; |
427 | } |
428 | print(tag: "counter_clockwise = " , count, ch: '\n'); |
429 | } |
430 | |
431 | void try_clockwise() |
432 | { |
433 | typedef boost::chrono::steady_clock Clock; |
434 | unsigned count = 0; |
435 | Clock::time_point until = Clock::now() + boost::chrono::seconds(3); |
436 | while (Clock::now() < until) |
437 | { |
438 | if (mut.try_lock_shared()) |
439 | { |
440 | assert(state == reading); |
441 | if (mut.try_unlock_shared_and_lock()) |
442 | { |
443 | state = writing; |
444 | } |
445 | else if (mut.try_unlock_shared_and_lock_upgrade()) |
446 | { |
447 | assert(state == reading); |
448 | mut.unlock_upgrade_and_lock(); |
449 | state = writing; |
450 | } |
451 | else |
452 | { |
453 | mut.unlock_shared(); |
454 | continue; |
455 | } |
456 | assert(state == writing); |
457 | state = reading; |
458 | mut.unlock_and_lock_upgrade(); |
459 | assert(state == reading); |
460 | mut.unlock_upgrade_and_lock_shared(); |
461 | assert(state == reading); |
462 | mut.unlock_shared(); |
463 | ++count; |
464 | } |
465 | } |
466 | print(tag: "try_clockwise = " , count, ch: '\n'); |
467 | } |
468 | |
469 | void try_for_clockwise() |
470 | { |
471 | typedef boost::chrono::steady_clock Clock; |
472 | unsigned count = 0; |
473 | Clock::time_point until = Clock::now() + boost::chrono::seconds(3); |
474 | while (Clock::now() < until) |
475 | { |
476 | if (mut.try_lock_shared_for(rel_time: boost::chrono::microseconds(5))) |
477 | { |
478 | assert(state == reading); |
479 | if (mut.try_unlock_shared_and_lock_for(rel_time: boost::chrono::microseconds(5))) |
480 | { |
481 | state = writing; |
482 | } |
483 | else if (mut.try_unlock_shared_and_lock_upgrade_for(rel_time: boost::chrono::microseconds(5))) |
484 | { |
485 | assert(state == reading); |
486 | mut.unlock_upgrade_and_lock(); |
487 | state = writing; |
488 | } |
489 | else |
490 | { |
491 | mut.unlock_shared(); |
492 | continue; |
493 | } |
494 | assert(state == writing); |
495 | state = reading; |
496 | mut.unlock_and_lock_upgrade(); |
497 | assert(state == reading); |
498 | mut.unlock_upgrade_and_lock_shared(); |
499 | assert(state == reading); |
500 | mut.unlock_shared(); |
501 | ++count; |
502 | } |
503 | } |
504 | print(tag: "try_for_clockwise = " , count, ch: '\n'); |
505 | } |
506 | |
507 | void try_counter_clockwise() |
508 | { |
509 | typedef boost::chrono::steady_clock Clock; |
510 | unsigned count = 0; |
511 | Clock::time_point until = Clock::now() + boost::chrono::seconds(3); |
512 | while (Clock::now() < until) |
513 | { |
514 | if (mut.try_lock_upgrade()) |
515 | { |
516 | assert(state == reading); |
517 | if (mut.try_unlock_upgrade_and_lock()) |
518 | { |
519 | assert(state == reading); |
520 | state = writing; |
521 | assert(state == writing); |
522 | state = reading; |
523 | mut.unlock_and_lock_shared(); |
524 | assert(state == reading); |
525 | mut.unlock_shared(); |
526 | ++count; |
527 | } |
528 | else |
529 | { |
530 | mut.unlock_upgrade(); |
531 | } |
532 | } |
533 | } |
534 | print(tag: "try_counter_clockwise = " , count, ch: '\n'); |
535 | } |
536 | |
537 | void try_for_counter_clockwise() |
538 | { |
539 | typedef boost::chrono::steady_clock Clock; |
540 | unsigned count = 0; |
541 | Clock::time_point until = Clock::now() + boost::chrono::seconds(3); |
542 | while (Clock::now() < until) |
543 | { |
544 | if (mut.try_lock_upgrade_for(rel_time: boost::chrono::microseconds(5))) |
545 | { |
546 | assert(state == reading); |
547 | if (mut.try_unlock_upgrade_and_lock_for(rel_time: boost::chrono::microseconds(5))) |
548 | { |
549 | assert(state == reading); |
550 | state = writing; |
551 | assert(state == writing); |
552 | state = reading; |
553 | mut.unlock_and_lock_shared(); |
554 | assert(state == reading); |
555 | mut.unlock_shared(); |
556 | ++count; |
557 | } |
558 | else |
559 | { |
560 | mut.unlock_upgrade(); |
561 | } |
562 | } |
563 | } |
564 | print(tag: "try_for_counter_clockwise = " , count, ch: '\n'); |
565 | } |
566 | |
567 | void |
568 | test_upgrade_mutex() |
569 | { |
570 | std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl; |
571 | { |
572 | boost::thread t1(reader); |
573 | boost::thread t2(writer); |
574 | boost::thread t3(reader); |
575 | t1.join(); |
576 | t2.join(); |
577 | t3.join(); |
578 | } |
579 | std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl; |
580 | { |
581 | boost::thread t1(try_reader); |
582 | boost::thread t2(try_writer); |
583 | boost::thread t3(try_reader); |
584 | t1.join(); |
585 | t2.join(); |
586 | t3.join(); |
587 | } |
588 | std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl; |
589 | { |
590 | boost::thread t1(try_for_reader); |
591 | boost::thread t2(try_for_writer); |
592 | boost::thread t3(try_for_reader); |
593 | t1.join(); |
594 | t2.join(); |
595 | t3.join(); |
596 | } |
597 | std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl; |
598 | { |
599 | boost::thread t1(reader); |
600 | boost::thread t2(writer); |
601 | boost::thread t3(upgradable); |
602 | t1.join(); |
603 | t2.join(); |
604 | t3.join(); |
605 | } |
606 | std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl; |
607 | { |
608 | boost::thread t1(reader); |
609 | boost::thread t2(writer); |
610 | boost::thread t3(try_upgradable); |
611 | t1.join(); |
612 | t2.join(); |
613 | t3.join(); |
614 | } |
615 | std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl; |
616 | { |
617 | boost::thread t1(reader); |
618 | boost::thread t2(writer); |
619 | boost::thread t3(try_for_upgradable); |
620 | t1.join(); |
621 | t2.join(); |
622 | t3.join(); |
623 | } |
624 | std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl; |
625 | { |
626 | state = reading; |
627 | boost::thread t1(clockwise); |
628 | boost::thread t2(counter_clockwise); |
629 | boost::thread t3(clockwise); |
630 | boost::thread t4(counter_clockwise); |
631 | t1.join(); |
632 | t2.join(); |
633 | t3.join(); |
634 | t4.join(); |
635 | } |
636 | std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl; |
637 | { |
638 | state = reading; |
639 | boost::thread t1(try_clockwise); |
640 | boost::thread t2(try_counter_clockwise); |
641 | t1.join(); |
642 | t2.join(); |
643 | } |
644 | std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl; |
645 | // { |
646 | // state = reading; |
647 | // boost::thread t1(try_for_clockwise); |
648 | // boost::thread t2(try_for_counter_clockwise); |
649 | // t1.join(); |
650 | // t2.join(); |
651 | // } |
652 | // std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl; |
653 | } |
654 | |
655 | } |
656 | |
657 | namespace Assignment |
658 | { |
659 | |
660 | class A |
661 | { |
662 | typedef boost::upgrade_mutex mutex_type; |
663 | typedef boost::shared_lock<mutex_type> SharedLock; |
664 | typedef boost::upgrade_lock<mutex_type> UpgradeLock; |
665 | typedef boost::unique_lock<mutex_type> Lock; |
666 | |
667 | mutable mutex_type mut_; |
668 | std::vector<double> data_; |
669 | |
670 | public: |
671 | |
672 | A(const A& a) |
673 | { |
674 | SharedLock _(a.mut_); |
675 | data_ = a.data_; |
676 | } |
677 | |
678 | A& operator=(const A& a) |
679 | { |
680 | if (this != &a) |
681 | { |
682 | Lock this_lock(mut_, boost::defer_lock); |
683 | SharedLock that_lock(a.mut_, boost::defer_lock); |
684 | boost::lock(m1&: this_lock, m2&: that_lock); |
685 | data_ = a.data_; |
686 | } |
687 | return *this; |
688 | } |
689 | |
690 | void swap(A& a) |
691 | { |
692 | Lock this_lock(mut_, boost::defer_lock); |
693 | Lock that_lock(a.mut_, boost::defer_lock); |
694 | boost::lock(m1&: this_lock, m2&: that_lock); |
695 | data_.swap(x&: a.data_); |
696 | } |
697 | |
698 | void average(A& a) |
699 | { |
700 | assert(data_.size() == a.data_.size()); |
701 | assert(this != &a); |
702 | |
703 | Lock this_lock(mut_, boost::defer_lock); |
704 | UpgradeLock share_that_lock(a.mut_, boost::defer_lock); |
705 | boost::lock(m1&: this_lock, m2&: share_that_lock); |
706 | |
707 | for (unsigned i = 0; i < data_.size(); ++i) |
708 | data_[i] = (data_[i] + a.data_[i]) / 2; |
709 | |
710 | SharedLock share_this_lock(boost::move(t&: this_lock)); |
711 | Lock that_lock(boost::move(t&: share_that_lock)); |
712 | a.data_ = data_; |
713 | } |
714 | }; |
715 | |
716 | } // Assignment |
717 | |
718 | void temp() |
719 | { |
720 | using namespace boost; |
721 | static upgrade_mutex mut; |
722 | unique_lock<upgrade_mutex> ul(mut); |
723 | shared_lock<upgrade_mutex> sl; |
724 | sl = BOOST_THREAD_MAKE_RV_REF(shared_lock<upgrade_mutex>(boost::move(ul))); |
725 | } |
726 | |
727 | int main() |
728 | { |
729 | std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl; |
730 | typedef boost::chrono::high_resolution_clock Clock; |
731 | typedef boost::chrono::duration<double> sec; |
732 | Clock::time_point t0 = Clock::now(); |
733 | |
734 | std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl; |
735 | S::test_shared_mutex(); |
736 | std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl; |
737 | U::test_upgrade_mutex(); |
738 | std::cout << __FILE__ << "[" <<__LINE__ << "]" << std::endl; |
739 | Clock::time_point t1 = Clock::now(); |
740 | std::cout << sec(t1 - t0) << '\n'; |
741 | return 0; |
742 | } |
743 | |
744 | #else |
745 | #error "This platform doesn't support Boost.Chrono" |
746 | #endif |
747 | |