Photon microGUI widgets library 0.6.0
mutex.hpp
1#ifndef _STDEX_MUTEX_H
2#define _STDEX_MUTEX_H
3
4#if _MSC_VER > 1000
5#pragma once
6#endif // _MSC_VER > 1000
7
8// stdex includes
9#include "./system_error.hpp"
10#include "./chrono.hpp"
11#include "./condition_variable.hpp"
12#include "./thread.hpp"
13
14// POSIX includes
15#include <pthread.h>
16
17// std includes
18#include <algorithm>
19
20#ifdef _STDEX_NATIVE_CPP11_SUPPORT
21
22#define _STDEX_DELETED_FUNCTION =delete
23#define _STDEX_NOEXCEPT_FUNCTION noexcept
24#define _STDEX_NOEXCEPT(args) noexcept(args)
25
26#else
27
28#define _STDEX_DELETED_FUNCTION
29#define _STDEX_NOEXCEPT_FUNCTION throw()
30#define _STDEX_NOEXCEPT(args)
31
32#endif
33
34
35namespace stdex
36{
37 namespace detail
38 {
39 class _mutex_base
40 {
41 protected:
42
43 pthread_mutex_t _mutex_handle;
44
45 _mutex_base() _STDEX_NOEXCEPT_FUNCTION
46 {
47 // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
48 int _err = pthread_mutex_init(&_mutex_handle, NULL);
49 if (0 != _err)
50 _throw_system_error(stdex::errc::errc_t(_err));
51 }
52
53 ~_mutex_base() _STDEX_NOEXCEPT(false)
54 {
55 int _err = pthread_mutex_destroy(&_mutex_handle);
56 if (0 != _err)
57 _throw_system_error(stdex::errc::errc_t(_err));
58 }
59
60 private:
61 _mutex_base(const _mutex_base&) _STDEX_DELETED_FUNCTION;
62 _mutex_base& operator=(const _mutex_base&) _STDEX_DELETED_FUNCTION;
63 };
64
65 class _recursive_mutex_base
66 {
67 protected:
68 pthread_mutex_t _mutex_handle;
69
70 _recursive_mutex_base()
71 {
72 pthread_mutexattr_t attr;
73
74 int _err = pthread_mutexattr_init(&attr);
75
76 if (0 == _err)
77 {
78 _err = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
79
80 if (0 == _err)
81 _err = pthread_mutex_init(&_mutex_handle, &attr); // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
82 }
83
84 if (0 != _err)
85 throw(
86 stdex::system_error(
87 stdex::make_error_code(stdex::errc::errc_t(_err))
88 )
89 );
90 }
91
92 ~_recursive_mutex_base() _STDEX_NOEXCEPT(false)
93 {
94 int _err = pthread_mutex_destroy(&_mutex_handle);
95 if (0 != _err)
96 _throw_system_error(stdex::errc::errc_t(_err));
97 }
98
99 private:
100 _recursive_mutex_base(const _recursive_mutex_base&) _STDEX_DELETED_FUNCTION;
101 _recursive_mutex_base& operator=(const _recursive_mutex_base&) _STDEX_DELETED_FUNCTION;
102 };
103 }
104
105 class mutex:
106 private detail::_mutex_base
107 {
108 public:
109 typedef pthread_mutex_t* native_handle_type;
110
111 mutex() _STDEX_NOEXCEPT_FUNCTION
112 {}
113
114 ~mutex()
115 {}
116
117 inline void lock()
118 {
119 int _err = pthread_mutex_lock(&_mutex_handle);
120
121 // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
122 if (0 != _err)
123 throw system_error(
124 stdex::make_error_code(stdex::errc::errc_t(_err))
125 );
126 }
127
128 inline bool try_lock() _STDEX_NOEXCEPT_FUNCTION
129 {
130 // XXX EINVAL, EAGAIN, EBUSY
131 return (pthread_mutex_trylock(&_mutex_handle) == 0) ? true : false;
132 }
133
134 inline void unlock()
135 {
136 int _err = pthread_mutex_unlock(&_mutex_handle);
137
138 if (0 != _err)
139 throw system_error(
140 stdex::make_error_code(stdex::errc::errc_t(_err))
141 );
142 }
143
144 native_handle_type native_handle() _STDEX_NOEXCEPT_FUNCTION
145 {
146 return &_mutex_handle;
147 }
148
149 private:
150
151 mutex(const mutex&) _STDEX_DELETED_FUNCTION;
152 mutex& operator=(const mutex&) _STDEX_DELETED_FUNCTION;
153 };
154
155 class recursive_mutex :
156 private detail::_recursive_mutex_base
157 {
158 public:
159 typedef pthread_mutex_t* native_handle_type;
160
161 recursive_mutex()
162 {}
163
164 ~recursive_mutex()
165 {}
166
167 inline void lock()
168 {
169 int _err = pthread_mutex_lock(&_mutex_handle);
170
171 // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
172 if (0 != _err)
173 throw system_error(
174 stdex::make_error_code(stdex::errc::errc_t(_err))
175 );
176 }
177
178 inline bool try_lock()
179 {
180 // XXX EINVAL, EAGAIN, EBUSY
181 return (pthread_mutex_trylock(&_mutex_handle) == 0) ? true : false;
182 }
183
184 inline void unlock()
185 {
186 int _err = pthread_mutex_unlock(&_mutex_handle);
187 // XXX EINVAL, EAGAIN, EBUSY
188 if (0 != _err)
189 throw system_error(
190 stdex::make_error_code(stdex::errc::errc_t(_err))
191 );
192 }
193
194 native_handle_type native_handle() _STDEX_NOEXCEPT_FUNCTION
195 {
196 return &_mutex_handle;
197 }
198
199 private:
200
201 recursive_mutex(const recursive_mutex&) _STDEX_DELETED_FUNCTION;
202 recursive_mutex& operator=(const recursive_mutex&) _STDEX_DELETED_FUNCTION;
203 };
204
205 // LOCK PROPERTIES
206 struct adopt_lock_t
207 {};
208
209 struct defer_lock_t
210 {};
211
212 struct try_to_lock_t
213 {};
214
215 extern const adopt_lock_t adopt_lock;
216 extern const defer_lock_t defer_lock;
217 extern const try_to_lock_t try_to_lock;
218
219 template <class _Lockbl>
220 class lock_guard {
221 public:
222 typedef _Lockbl mutex_type;
223
224 explicit lock_guard(mutex_type &_m):
225 _device(_m)
226 {
227 _device.lock();
228 }
229
230 lock_guard(mutex_type &_m, adopt_lock_t) _STDEX_NOEXCEPT_FUNCTION:
231 _device(_m)
232 {}
233
234 ~lock_guard()
235 {
236 _device.unlock();
237 }
238
239
240 private:
241 mutex_type &_device;
242
243 lock_guard(const lock_guard&) _STDEX_DELETED_FUNCTION;
244 lock_guard& operator=(const lock_guard&) _STDEX_DELETED_FUNCTION;
245 };
246
247 template<class _Lockbl>
248 class unique_lock
249 {
250 public:
251 typedef _Lockbl mutex_type;
252
253 unique_lock() _STDEX_NOEXCEPT_FUNCTION :
254 _device(0),
255 _owns(false)
256 { }
257
258 explicit unique_lock(mutex_type &_m):
259 _device(&(_m)),
260 _owns(false)
261 {
262 lock();
263 _owns = true;
264 }
265
266 unique_lock(mutex_type &_m, defer_lock_t) _STDEX_NOEXCEPT_FUNCTION:
267 _device(&(_m)),
268 _owns(false)
269 { }
270
271 unique_lock(mutex_type &_m, try_to_lock_t):
272 _device(&(_m)),
273 _owns(_device->try_lock())
274 { }
275
276 unique_lock(mutex_type &_m, adopt_lock_t) _STDEX_NOEXCEPT_FUNCTION:
277 _device(&(_m)),
278 _owns(true)
279 {
280 // XXX calling thread owns mutex
281 }
282
283 template<class _Clock, class _Duration>
284 unique_lock(mutex_type &_m, const chrono::time_point<_Clock, _Duration> &atime):
285 _device(&(_m)),
286 _owns(_device->try_lock_until(atime))
287 { }
288
289 template<class _Rep, class _Period>
290 unique_lock(mutex_type &_m, const chrono::duration<_Rep, _Period> &rtime):
291 _device(&(_m)),
292 _owns(_device->try_lock_for(rtime))
293 { }
294
295 ~unique_lock()
296 {
297 if (_owns)
298 unlock();
299 }
300
301 /* move move move, no move in pre-C++11
302 unique_lock(unique_lock &&u) _STDEX_NOEXCEPT_FUNCTION:
303 _device(u._device),
304 _owns(u._owns)
305 {
306 u._device = 0;
307 u._owns = false;
308 }
309
310 unique_lock& operator=(unique_lock &&u) _STDEX_NOEXCEPT_FUNCTION
311 {
312 if (_owns)
313 unlock();
314
315 unique_lock(std::move(u)).swap(*this);
316
317 u._device = 0;
318 u._owns = false;
319
320 return *this;
321 }
322 */
323
324 void lock()
325 {
326 if (!_device)
327 throw system_error(
328 stdex::make_error_code(errc::operation_not_permitted)
329 );
330 else if (_owns)
331 throw system_error(
332 stdex::make_error_code(errc::resource_deadlock_would_occur)
333 );
334 else
335 {
336 _device->lock();
337 _owns = true;
338 }
339 }
340
341 bool try_lock()
342 {
343 if (!_device)
344 throw system_error(
345 stdex::make_error_code(errc::operation_not_permitted)
346 );
347 else if (_owns)
348 throw system_error(
349 stdex::make_error_code(errc::resource_deadlock_would_occur)
350 );
351 else
352 {
353 _owns = _device->try_lock();
354 return _owns;
355 }
356 }
357
358 template<class _Clock, class _Duration>
359 bool try_lock_until(const chrono::time_point<_Clock, _Duration> &atime)
360 {
361 if (!_device)
362 throw system_error(
363 stdex::make_error_code(errc::operation_not_permitted)
364 );
365 else if (_owns)
366 throw system_error(
367 stdex::make_error_code(errc::resource_deadlock_would_occur)
368 );
369 else
370 {
371 _owns = _device->try_lock_until(atime);
372 return _owns;
373 }
374 }
375
376 template<class _Rep, class _Period>
377 bool try_lock_for(const chrono::duration<_Rep, _Period> &rtime)
378 {
379 if (!_device)
380 throw system_error(
381 stdex::make_error_code(errc::operation_not_permitted)
382 );
383 else if (_owns)
384 throw system_error(
385 stdex::make_error_code(errc::resource_deadlock_would_occur)
386 );
387 else
388 {
389 _owns = _device->try_lock_for(rtime);
390 return _owns;
391 }
392 }
393
394 void unlock()
395 {
396 if (!_owns)
397 throw system_error(
398 stdex::make_error_code(errc::operation_not_permitted)
399 );
400 else if (_device)
401 {
402 _device->unlock();
403 _owns = false;
404 }
405 }
406
407 void swap(unique_lock &other) _STDEX_NOEXCEPT_FUNCTION
408 {
409 {
410 mutex_type *tmp_value = _device;
411 _device = other._device;
412 other._device = tmp_value;
413 }
414
415 {
416 bool tmp_value = _owns;
417 _owns = other._owns;
418 other._owns = tmp_value;
419 }
420 }
421
422 mutex_type* release() _STDEX_NOEXCEPT_FUNCTION
423 {
424 mutex_type *ret = _device;
425 _device = 0;
426 _owns = false;
427 return ret;
428 }
429
430 bool owns_lock() const _STDEX_NOEXCEPT_FUNCTION
431 {
432 return _owns;
433 }
434
435 operator bool() const _STDEX_NOEXCEPT_FUNCTION
436 {
437 return owns_lock();
438 }
439
440 mutex_type* mutex() const _STDEX_NOEXCEPT_FUNCTION
441 {
442 return _device;
443 }
444
445 private:
446 mutex_type *_device;
447 bool _owns; // XXX use atomic_bool
448
449 unique_lock(const unique_lock&) _STDEX_DELETED_FUNCTION;
450 unique_lock& operator=(const unique_lock&) _STDEX_DELETED_FUNCTION;
451 };
452
453 class timed_mutex;
454 class recursive_timed_mutex;
455
456 namespace detail
457 {
458
459 namespace mutex_type_traits
460 {
461#ifndef PTW32_VERSION
462 float* pthread_mutex_timedlock(...); // dummy
463#endif
464
465 template<class _Tp>
466 _Tp declval();
467
468 _yes_type _pthread_func_tester(int);
469 _no_type _pthread_func_tester(...);
470
471 struct _has_pthread_mutex_timedlock
472 {
473 static const bool value =
474 sizeof(
475 _pthread_func_tester(
476 pthread_mutex_timedlock(
477 declval< ::pthread_mutex_t*>(),
478 declval< ::timespec* >()
479 )
480 )
481 ) == sizeof(_yes_type);
482 };
483 }
484
485 struct _timed_mutex_with_timedlock
486 {
487
488 public:
489 template<class _Rep, class _Period>
490 static bool try_lock_for(pthread_mutex_t& _mutex_handle,
491 const chrono::duration<_Rep, _Period>& _rtime)
492 {
493 typedef chrono::system_clock _clock;
494
495 _clock::duration _rt =
496 chrono::duration_cast<_clock::duration>(_rtime);
497
498 const bool check =
499 ratio_greater<_clock::period, _Period>::value;
500 if (check)
501 ++_rt;
502 return try_lock_until1(_mutex_handle, _clock::now() + _rt);
503 }
504
505 template<class _Duration, class _MtxHandle>
506 static bool try_lock_until1(_MtxHandle& _mutex_handle,
507 const chrono::time_point<chrono::system_clock, _Duration>& _atime)
508 {
509 stdex::timespec _tp_as_ts =
510 chrono::system_clock::to_timespec(_atime);
511
512 ::timespec _ts;
513
514 _ts.tv_nsec = _tp_as_ts.tv_nsec;
515 _ts.tv_sec = _tp_as_ts.tv_sec;
516
517 bool success =
518 (pthread_mutex_timedlock(&_mutex_handle, &_ts) == 0);
519
520 return success;
521 }
522
523 template<class _Clock, class _Duration>
524 static bool try_lock_until(pthread_mutex_t& _mutex_handle,
525 const chrono::time_point<_Clock, _Duration>& _atime)
526 {
527 // The user-supplied clock may not tick at the same rate as
528 // steady_clock, so we must loop in order to guarantee that
529 // the timeout has expired before returning false.
530 typename _Clock::time_point _now = _Clock::now();
531 do {
532 typename _Clock::duration _rtime = _atime - _now;
533 if (try_lock_for(_mutex_handle, _rtime))
534 return true;
535 _now = _Clock::now();
536 } while (_atime > _now);
537 return false;
538 }
539 };
540
541 template<class, bool>
542 class _timed_mutex_impl_base;
543
544 // without pthread_mutex_timedlock support
545 template<>
546 class _timed_mutex_impl_base<_mutex_base, false>
547 {
548 struct _Pred
549 {
550 bool operator()() const {
551 return !*_locked;
552 }
553
554 bool* _locked;
555 } ;
556
557 public:
558
559 typedef mutex::native_handle_type native_handle_type;
560
561 ~_timed_mutex_impl_base()
562 {}
563
564 void lock()
565 {
566 unique_lock<mutex> _lk(_mut);
567
568 _Pred _pred;
569 _pred._locked = &_locked;
570
571 _cv.wait(_lk, _pred);
572 _locked = true;
573 }
574
575 bool try_lock()
576 {
577 lock_guard<mutex> _lk(_mut);
578 if (_locked)
579 return false;
580 _locked = true;
581 return true;
582 }
583
584 template<class _Rep, class _Period>
585 bool try_lock_for(const chrono::duration<_Rep, _Period>& _rtime)
586 {
587 unique_lock<mutex> _lk(_mut);
588
589 _Pred _pred;
590 _pred._locked = &_locked;
591
592 if (!_cv.wait_for(_lk, _rtime, _pred))
593 return false;
594 _locked = true;
595 return true;
596 }
597
598 template<class _Clock, class _Duration>
599 bool try_lock_until(const chrono::time_point<_Clock, _Duration>& _atime)
600 {
601 unique_lock<mutex> _lk(_mut);
602
603 _Pred _pred;
604 _pred._locked = &_locked;
605
606 if (!_cv.wait_until(_lk, _atime, _pred))
607 return false;
608 _locked = true;
609 return true;
610 }
611
612 void unlock()
613 {
614 lock_guard<mutex> _lk(_mut);
615
616 _locked = false;
617 _cv.notify_one();
618 }
619
620 native_handle_type native_handle() _STDEX_NOEXCEPT_FUNCTION
621 {
622 return _mut.native_handle();
623 }
624
625 protected:
626 _timed_mutex_impl_base() _STDEX_NOEXCEPT_FUNCTION:
627 _locked(false)
628 {}
629
630 private:
631
632 mutex _mut;
633 condition_variable _cv;
634 bool _locked;
635 };
636
637 template<>
638 class _timed_mutex_impl_base<_recursive_mutex_base, false>
639 {
640 // Predicate type that tests whether the current thread can lock a mutex.
641 class _Can_lock
642 {
643 public:
644 // Returns true if the mutex is unlocked or is locked by _caller.
645 bool operator()() const _STDEX_NOEXCEPT_FUNCTION
646 {
647 return _mx->_count == 0 || _mx->_owner == _caller;
648 }
649
650 const _timed_mutex_impl_base<_recursive_mutex_base, false>* _mx;
651 thread::id _caller;
652 };
653
654 friend class _timed_mutex_impl_base<_recursive_mutex_base, false>::_Can_lock;
655
656 public:
657
658 typedef mutex::native_handle_type native_handle_type;
659
660 ~_timed_mutex_impl_base()
661 {}
662
663 void lock()
664 {
665 thread::id _id = this_thread::get_id();
666 _Can_lock _can_lock;
667
668 _can_lock._mx = this;
669 _can_lock._caller = _id;
670
671 unique_lock<mutex> _lk(_mut);
672 _cv.wait(_lk, _can_lock);
673 if ((0u - 1u) == _count)
674 throw system_error(
675 stdex::make_error_code(stdex::errc::errc_t(EAGAIN))
676 );// [thread.timedmutex.recursive]/3
677 _owner = _id;
678 ++_count;
679 }
680
681 bool try_lock()
682 {
683 thread::id _id = this_thread::get_id();
684 _Can_lock _can_lock;
685
686 _can_lock._mx = this;
687 _can_lock._caller = _id;
688
689 lock_guard<mutex> _lk(_mut);
690 if (!_can_lock())
691 return false;
692 if ((0u - 1u) == _count)
693 return false;
694 _owner = _id;
695 ++_count;
696 return true;
697 }
698
699 template<class _Rep, class _Period>
700 bool try_lock_for(const chrono::duration<_Rep, _Period>& _rtime)
701 {
702 thread::id _id = this_thread::get_id();
703 _Can_lock _can_lock;
704
705 _can_lock._mx = this;
706 _can_lock._caller = _id;
707
708 unique_lock<mutex> _lk(_mut);
709 if (!_cv.wait_for(_lk, _rtime, _can_lock))
710 return false;
711 if ((0u - 1u) == _count)
712 return false;
713 _owner = _id;
714 ++_count;
715 return true;
716 }
717
718 template<class _Clock, class _Duration>
719 bool try_lock_until(const chrono::time_point<_Clock, _Duration>& _atime)
720 {
721 thread::id _id = this_thread::get_id();
722 _Can_lock _can_lock;
723
724 _can_lock._mx = this;
725 _can_lock._caller = _id;
726
727 unique_lock<mutex> _lk(_mut);
728 if (!_cv.wait_until(_lk, _atime, _can_lock))
729 return false;
730 if ((0u - 1u) == _count)
731 return false;
732 _owner = _id;
733 ++_count;
734 return true;
735 }
736
737 void unlock()
738 {
739 lock_guard<mutex> _lk(_mut);
740
741 if (--_count == 0)
742 {
743 _owner = thread::id();
744 _cv.notify_one();
745 }
746 }
747
748 native_handle_type native_handle() _STDEX_NOEXCEPT_FUNCTION
749 {
750 return _mut.native_handle();
751 }
752
753 protected:
754 _timed_mutex_impl_base() _STDEX_NOEXCEPT_FUNCTION :
755 _count(0)
756 {}
757
758 private:
759
760 mutex _mut;
761 condition_variable _cv;
762 thread::id _owner;
763 unsigned _count;
764
765 _timed_mutex_impl_base(const _timed_mutex_impl_base&) _STDEX_DELETED_FUNCTION;
766 _timed_mutex_impl_base& operator=(const _timed_mutex_impl_base&) _STDEX_DELETED_FUNCTION;
767 };
768
769 // with pthread_mutex_timedlock support
770 template<>
771 class _timed_mutex_impl_base<_mutex_base, true> :
772 private _mutex_base
773 {
774 public:
775
776 typedef mutex::native_handle_type native_handle_type;
777
778 ~_timed_mutex_impl_base()
779 {}
780
781 inline void lock()
782 {
783 int _err = pthread_mutex_lock(&_mutex_handle);
784
785 // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
786 if (_err)
787 throw system_error(
788 stdex::make_error_code(stdex::errc::errc_t(_err))
789 );
790 }
791
792 inline bool try_lock() _STDEX_NOEXCEPT_FUNCTION
793 {
794 // XXX EINVAL, EAGAIN, EBUSY
795 return (pthread_mutex_trylock(&_mutex_handle) == 0) ? true : false;
796 }
797
798 template <class _Rep, class _Period>
799 bool try_lock_for(const chrono::duration<_Rep, _Period>& _rtime)
800 {
801 return _timed_mutex_with_timedlock::try_lock_for(_mutex_handle, _rtime);
802 }
803
804 template <class _Clock, class _Duration>
805 bool try_lock_until(const chrono::time_point<_Clock, _Duration>& _atime)
806 {
807 return _timed_mutex_with_timedlock::try_lock_until(_mutex_handle, _atime);
808 }
809
810 inline void unlock()
811 {
812 pthread_mutex_unlock(&_mutex_handle);
813 }
814
815 native_handle_type native_handle() _STDEX_NOEXCEPT_FUNCTION
816 {
817 return &_mutex_handle;
818 }
819
820 protected:
821
822 _timed_mutex_impl_base() _STDEX_NOEXCEPT_FUNCTION
823 {}
824
825 private:
826
827 _timed_mutex_impl_base(const _timed_mutex_impl_base&) _STDEX_DELETED_FUNCTION;
828 _timed_mutex_impl_base& operator=(const _timed_mutex_impl_base&) _STDEX_DELETED_FUNCTION;
829 };
830
831 template<>
832 class _timed_mutex_impl_base<_recursive_mutex_base, true> :
833 private _recursive_mutex_base
834 {
835 public:
836
837 typedef mutex::native_handle_type native_handle_type;
838
839 ~_timed_mutex_impl_base()
840 {}
841
842 inline void lock()
843 {
844 int _err = pthread_mutex_lock(&_mutex_handle);
845
846 // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
847 if (_err)
848 throw system_error(
849 stdex::make_error_code(stdex::errc::errc_t(_err))
850 );
851 }
852
853 inline bool try_lock()
854 {
855 // XXX EINVAL, EAGAIN, EBUSY
856 return (pthread_mutex_trylock(&_mutex_handle) == 0) ? true : false;
857 }
858
859 template <class _Rep, class _Period>
860 bool try_lock_for(const chrono::duration<_Rep, _Period>& _rtime)
861 {
862 return _timed_mutex_with_timedlock::try_lock_for(_mutex_handle, _rtime);
863 }
864
865 template <class _Clock, class _Duration>
866 bool try_lock_until(const chrono::time_point<_Clock, _Duration>& _atime)
867 {
868 return _timed_mutex_with_timedlock::try_lock_until(_mutex_handle, _atime);
869 }
870
871 inline void unlock()
872 {
873 // XXX EINVAL, EAGAIN, EBUSY
874 pthread_mutex_unlock(&_mutex_handle);
875 }
876
877 native_handle_type native_handle() _STDEX_NOEXCEPT_FUNCTION
878 {
879 return &_mutex_handle;
880 }
881
882 protected:
883
884 _timed_mutex_impl_base()
885 {}
886
887 private:
888
889 _timed_mutex_impl_base(const _timed_mutex_impl_base&) _STDEX_DELETED_FUNCTION;
890 _timed_mutex_impl_base& operator=(const _timed_mutex_impl_base&) _STDEX_DELETED_FUNCTION;
891 };
892
893 template<class>
894 class _timed_mutex_impl;
895
896 template<>
897 class _timed_mutex_impl<timed_mutex> :
898 public _timed_mutex_impl_base<
899 _mutex_base,
900 mutex_type_traits::_has_pthread_mutex_timedlock::value
901 >
902 {
903 protected:
904 _timed_mutex_impl() _STDEX_NOEXCEPT_FUNCTION
905 {}
906 };
907
908 template<>
909 class _timed_mutex_impl<recursive_timed_mutex> :
910 public _timed_mutex_impl_base<
911 _recursive_mutex_base,
912 mutex_type_traits::_has_pthread_mutex_timedlock::value
913 >
914 {
915 protected:
916 _timed_mutex_impl()
917 {}
918 };
919 }
920
921 class timed_mutex :
922 public detail::_timed_mutex_impl<timed_mutex>
923 { };
924
925 class recursive_timed_mutex :
926 public detail::_timed_mutex_impl<recursive_timed_mutex>
927 { };
928
930 template<class _Lockbl>
931 inline void swap(stdex::unique_lock<_Lockbl> &lhs, stdex::unique_lock<_Lockbl> &rhs) _STDEX_NOEXCEPT_FUNCTION
932 {
933 lhs.swap(rhs);
934 }
935
936 namespace detail
937 {
938 pthread_mutex_t* _lock_mutex_native_handle(const unique_lock<mutex>&);
939 bool _lock_owns_lock(const unique_lock<mutex>&);
940 } // namespace detail
941
942} // namespace stdex
943
944// mutex algorithms
945
946namespace stdex
947{
948 namespace detail
949 {
950
951 namespace
952 {
953 template <class _Lockbl1, class _Lockbl2>
954 unsigned int _try_lock(_Lockbl1 &_m1, _Lockbl2 &_m2)
955 {
956 stdex::unique_lock<_Lockbl1> _l1(_m1, stdex::try_to_lock);
957
958 if (!_l1)
959 return 1;
960
961 if (!_m2.try_lock())
962 return 2;
963
964 _l1.release();
965 return 0;
966 }
967
968 template <class _Lockbl1, class _Lockbl2>
969 unsigned int _lock_helper(_Lockbl1 &_m1, _Lockbl2 &_m2)
970 {
971 stdex::unique_lock<_Lockbl1> _l1(_m1);
972 if (!_m2.try_lock())
973 return 1;
974
975 _l1.release();
976 return 0;
977 }
978
979// some boilreplate code:
980
981#undef _STDEX_TRY_LOCK
982#undef _STDEX_LOCK_HELPER
983
984#undef _STDEX_TYPES
985#undef _STDEX_ARGS
986#undef _STDEX_ARGS_NAMES
987
988#define _STDEX_TRY_LOCK(N) \
989 template <class _Lockbl1, _STDEX_TYPES##N > \
990 unsigned int _try_lock(_Lockbl1 &_m1, _STDEX_ARGS##N ) \
991 { \
992 stdex::unique_lock<_Lockbl1> _l1(_m1, stdex::try_to_lock); \
993 if (!_l1) \
994 return 1; \
995 \
996 const unsigned int _failed_lock = _try_lock(_STDEX_ARGS_NAMES##N ); \
997 \
998 if (_failed_lock > 0) \
999 return _failed_lock + 1; \
1000 \
1001 _l1.release();\
1002 return 0;\
1003 } \
1004 template <class _Lockbl1, _STDEX_TYPES##N > \
1005 int try_lock(_Lockbl1 &_m1, _STDEX_ARGS##N ) \
1006 { \
1007 return ((int) _try_lock(_m1, _STDEX_ARGS_NAMES##N )) - 1; \
1008 }
1009
1010#define _STDEX_LOCK_HELPER(N) \
1011 template <class _Lockbl1, _STDEX_TYPES##N > \
1012 unsigned int _lock_helper(_Lockbl1 &_m1, _STDEX_ARGS##N ) \
1013 { \
1014 stdex::unique_lock<_Lockbl1> _l1(_m1); \
1015 const unsigned int _failed_lock = _try_lock(_STDEX_ARGS_NAMES##N ); \
1016 if (_failed_lock > 0) \
1017 return _failed_lock; \
1018 \
1019 _l1.release(); \
1020 return 0; \
1021 }
1022
1023
1024
1025#define _STDEX_TYPES_N(N) class _Lockbl##N
1026#define _STDEX_ARGS_N(N) _Lockbl##N &_m##N
1027#define _STDEX_ARGS_NAMES_N(N) _m##N
1028
1029#define _STDEX_TYPES3 class _Lockbl2, class _Lockbl3
1030#define _STDEX_ARGS3 _Lockbl2 &_m2, _Lockbl3 &_m3
1031#define _STDEX_ARGS_NAMES3 _m2, _m3
1032#define _STDEX_TYPES4 _STDEX_TYPES3 , _STDEX_TYPES_N (4)
1033#define _STDEX_ARGS4 _STDEX_ARGS3 , _STDEX_ARGS_N (4)
1034#define _STDEX_ARGS_NAMES4 _STDEX_ARGS_NAMES3 , _STDEX_ARGS_NAMES_N (4)
1035#define _STDEX_TYPES5 _STDEX_TYPES4 , _STDEX_TYPES_N (5)
1036#define _STDEX_ARGS5 _STDEX_ARGS4 , _STDEX_ARGS_N (5)
1037#define _STDEX_ARGS_NAMES5 _STDEX_ARGS_NAMES4 , _STDEX_ARGS_NAMES_N (5)
1038#define _STDEX_TYPES6 _STDEX_TYPES5 , _STDEX_TYPES_N (6)
1039#define _STDEX_ARGS6 _STDEX_ARGS5 , _STDEX_ARGS_N (6)
1040#define _STDEX_ARGS_NAMES6 _STDEX_ARGS_NAMES5 , _STDEX_ARGS_NAMES_N (6)
1041#define _STDEX_TYPES7 _STDEX_TYPES6 , _STDEX_TYPES_N (7)
1042#define _STDEX_ARGS7 _STDEX_ARGS6 , _STDEX_ARGS_N (7)
1043#define _STDEX_ARGS_NAMES7 _STDEX_ARGS_NAMES6 , _STDEX_ARGS_NAMES_N (7)
1044#define _STDEX_TYPES8 _STDEX_TYPES7 , _STDEX_TYPES_N (8)
1045#define _STDEX_ARGS8 _STDEX_ARGS7 , _STDEX_ARGS_N (8)
1046#define _STDEX_ARGS_NAMES8 _STDEX_ARGS_NAMES7 , _STDEX_ARGS_NAMES_N (8)
1047#define _STDEX_TYPES9 _STDEX_TYPES8 , _STDEX_TYPES_N (9)
1048#define _STDEX_ARGS9 _STDEX_ARGS8 , _STDEX_ARGS_N (9)
1049#define _STDEX_ARGS_NAMES9 _STDEX_ARGS_NAMES8 , _STDEX_ARGS_NAMES_N (9)
1050#define _STDEX_TYPES10 _STDEX_TYPES9 , _STDEX_TYPES_N (10)
1051#define _STDEX_ARGS10 _STDEX_ARGS9 , _STDEX_ARGS_N (10)
1052#define _STDEX_ARGS_NAMES10 _STDEX_ARGS_NAMES9 , _STDEX_ARGS_NAMES_N (10)
1053#define _STDEX_TYPES11 _STDEX_TYPES10, _STDEX_TYPES_N (11)
1054#define _STDEX_ARGS11 _STDEX_ARGS10, _STDEX_ARGS_N (11)
1055#define _STDEX_ARGS_NAMES11 _STDEX_ARGS_NAMES10, _STDEX_ARGS_NAMES_N (11)
1056#define _STDEX_TYPES12 _STDEX_TYPES11, _STDEX_TYPES_N (12)
1057#define _STDEX_ARGS12 _STDEX_ARGS11, _STDEX_ARGS_N (12)
1058#define _STDEX_ARGS_NAMES12 _STDEX_ARGS_NAMES11, _STDEX_ARGS_NAMES_N (12)
1059#define _STDEX_TYPES13 _STDEX_TYPES12, _STDEX_TYPES_N (13)
1060#define _STDEX_ARGS13 _STDEX_ARGS12, _STDEX_ARGS_N (13)
1061#define _STDEX_ARGS_NAMES13 _STDEX_ARGS_NAMES12, _STDEX_ARGS_NAMES_N (13)
1062#define _STDEX_TYPES14 _STDEX_TYPES13, _STDEX_TYPES_N (14)
1063#define _STDEX_ARGS14 _STDEX_ARGS13, _STDEX_ARGS_N (14)
1064#define _STDEX_ARGS_NAMES14 _STDEX_ARGS_NAMES13, _STDEX_ARGS_NAMES_N (14)
1065#define _STDEX_TYPES15 _STDEX_TYPES14, _STDEX_TYPES_N (15)
1066#define _STDEX_ARGS15 _STDEX_ARGS14, _STDEX_ARGS_N (15)
1067#define _STDEX_ARGS_NAMES15 _STDEX_ARGS_NAMES14, _STDEX_ARGS_NAMES_N (15)
1068#define _STDEX_TYPES16 _STDEX_TYPES15, _STDEX_TYPES_N (16)
1069#define _STDEX_ARGS16 _STDEX_ARGS15, _STDEX_ARGS_N (16)
1070#define _STDEX_ARGS_NAMES16 _STDEX_ARGS_NAMES15, _STDEX_ARGS_NAMES_N (16)
1071#define _STDEX_TYPES17 _STDEX_TYPES16, _STDEX_TYPES_N (17)
1072#define _STDEX_ARGS17 _STDEX_ARGS16, _STDEX_ARGS_N (17)
1073#define _STDEX_ARGS_NAMES17 _STDEX_ARGS_NAMES16, _STDEX_ARGS_NAMES_N (17)
1074#define _STDEX_TYPES18 _STDEX_TYPES17, _STDEX_TYPES_N (18)
1075#define _STDEX_ARGS18 _STDEX_ARGS17, _STDEX_ARGS_N (18)
1076#define _STDEX_ARGS_NAMES18 _STDEX_ARGS_NAMES17, _STDEX_ARGS_NAMES_N (18)
1077#define _STDEX_TYPES19 _STDEX_TYPES18, _STDEX_TYPES_N (19)
1078#define _STDEX_ARGS19 _STDEX_ARGS18, _STDEX_ARGS_N (19)
1079#define _STDEX_ARGS_NAMES19 _STDEX_ARGS_NAMES18, _STDEX_ARGS_NAMES_N (19)
1080#define _STDEX_TYPES20 _STDEX_TYPES19, _STDEX_TYPES_N (20)
1081#define _STDEX_ARGS20 _STDEX_ARGS19, _STDEX_ARGS_N (20)
1082#define _STDEX_ARGS_NAMES20 _STDEX_ARGS_NAMES19, _STDEX_ARGS_NAMES_N (20)
1083#define _STDEX_TYPES21 _STDEX_TYPES20, _STDEX_TYPES_N (21)
1084#define _STDEX_ARGS21 _STDEX_ARGS20, _STDEX_ARGS_N (21)
1085#define _STDEX_ARGS_NAMES21 _STDEX_ARGS_NAMES20, _STDEX_ARGS_NAMES_N (21)
1086#define _STDEX_TYPES22 _STDEX_TYPES21, _STDEX_TYPES_N (22)
1087#define _STDEX_ARGS22 _STDEX_ARGS21, _STDEX_ARGS_N (22)
1088#define _STDEX_ARGS_NAMES22 _STDEX_ARGS_NAMES21, _STDEX_ARGS_NAMES_N (22)
1089#define _STDEX_TYPES23 _STDEX_TYPES22, _STDEX_TYPES_N (23)
1090#define _STDEX_ARGS23 _STDEX_ARGS22, _STDEX_ARGS_N (23)
1091#define _STDEX_ARGS_NAMES23 _STDEX_ARGS_NAMES22, _STDEX_ARGS_NAMES_N (23)
1092#define _STDEX_TYPES24 _STDEX_TYPES23, _STDEX_TYPES_N (24)
1093#define _STDEX_ARGS24 _STDEX_ARGS23, _STDEX_ARGS_N (24)
1094#define _STDEX_ARGS_NAMES24 _STDEX_ARGS_NAMES23, _STDEX_ARGS_NAMES_N (24)
1095
1096#define _STDEX_LOCK_DEFINE(N) \
1097 _STDEX_TRY_LOCK(N) \
1098 _STDEX_LOCK_HELPER(N)
1099
1100 _STDEX_LOCK_DEFINE(3)
1101 _STDEX_LOCK_DEFINE(4)
1102 _STDEX_LOCK_DEFINE(5)
1103 _STDEX_LOCK_DEFINE(6)
1104 _STDEX_LOCK_DEFINE(7)
1105 _STDEX_LOCK_DEFINE(8)
1106 _STDEX_LOCK_DEFINE(9)
1107 _STDEX_LOCK_DEFINE(10)
1108 _STDEX_LOCK_DEFINE(11)
1109 _STDEX_LOCK_DEFINE(12)
1110 _STDEX_LOCK_DEFINE(13)
1111 _STDEX_LOCK_DEFINE(14)
1112 _STDEX_LOCK_DEFINE(15)
1113 _STDEX_LOCK_DEFINE(16)
1114 _STDEX_LOCK_DEFINE(17)
1115 _STDEX_LOCK_DEFINE(18)
1116 _STDEX_LOCK_DEFINE(19)
1117 _STDEX_LOCK_DEFINE(20)
1118 _STDEX_LOCK_DEFINE(21)
1119 _STDEX_LOCK_DEFINE(22)
1120 _STDEX_LOCK_DEFINE(23)
1121 _STDEX_LOCK_DEFINE(24)
1122
1123#undef _STDEX_TRY_LOCK
1124#undef _STDEX_LOCK_HELPER
1125#undef _STDEX_LOCK_DEFINE
1126 }
1127
1128 template <class _Lockbl1, class _Lockbl2>
1129 void _lock_impl(_Lockbl1 &_m1, _Lockbl2 &_m2)
1130 {
1131 const unsigned int _lock_count = 2;
1132 unsigned int _lock_first = 0;
1133 for (;;)
1134 {
1135 switch (_lock_first)
1136 {
1137 case 0:
1138 _lock_first = detail::_lock_helper(_m1, _m2);
1139 if (0 == _lock_first) return;
1140 break;
1141 case 1:
1142 _lock_first = detail::_lock_helper(_m2, _m1);
1143 if (0 == _lock_first) return;
1144 _lock_first = (_lock_first * 2) % _lock_count;
1145 break;
1146 }
1147 }
1148 }
1149
1150 template <class _It>
1151 void _lock_impl_iterators(_It begin, _It end);
1152
1153 template <class _Lockbl1, class _Lockbl2>
1154 int _try_lock_impl(_Lockbl1 &_m1, _Lockbl2 &_m2)
1155 {
1156 return ((int) detail::_try_lock(_m1, _m2)) - 1;
1157 }
1158
1159 template <class _It>
1160 _It _try_lock_impl_iterators(_It begin, _It end);
1161 } // namespace detail
1162
1163 template <class _Lockbl1, class _Lockbl2>
1164 void lock(_Lockbl1 &_m1, _Lockbl2 &_m2)
1165 {
1166 detail::_lock_impl(_m1, _m2);
1167 }
1168
1169 template <class _Lockbl1, class _Lockbl2>
1170 void lock(const _Lockbl1 &_m1, _Lockbl2 &_m2)
1171 {
1172 detail::_lock_impl(_m1, _m2);
1173 }
1174
1175 template <class _Lockbl1, class _Lockbl2>
1176 void lock(_Lockbl1 &_m1, const _Lockbl2 &_m2)
1177 {
1178 detail::_lock_impl(_m1, _m2);
1179 }
1180
1181 template <class _Lockbl1, class _Lockbl2>
1182 void lock(const _Lockbl1 &_m1, const _Lockbl2 &_m2)
1183 {
1184 detail::_lock_impl(_m1, _m2);
1185 }
1186
1187 template <class _Lockbl1, _STDEX_TYPES3>
1188 void lock(_Lockbl1 &_m1, _STDEX_ARGS3)
1189 {
1190 const unsigned int _lock_count = 3;
1191 unsigned int _lock_first = 0;
1192 for (;;)
1193 {
1194 switch (_lock_first)
1195 {
1196 case 0:
1197 _lock_first = detail::_lock_helper(_m1, _m2, _m3);
1198 if (0 == _lock_first) return;
1199 break;
1200 case 1:
1201 _lock_first = detail::_lock_helper(_m2, _m3, _m1);
1202 if (0 == _lock_first) return;
1203 _lock_first = (_lock_first * 2) % _lock_count;
1204 break;
1205 case 2:
1206 _lock_first = detail::_lock_helper(_m3, _m1, _m2);
1207 if (0 == _lock_first) return;
1208 _lock_first = (_lock_first * 2) % _lock_count;
1209 break;
1210 }
1211 }
1212 }
1213
1214 template <class _Lockbl1, _STDEX_TYPES4>
1215 void lock(_Lockbl1 &_m1, _STDEX_ARGS4)
1216 {
1217 const unsigned int _lock_count = 4;
1218 unsigned int _lock_first = 0;
1219 for (;;)
1220 {
1221 switch (_lock_first)
1222 {
1223 case 0:
1224 _lock_first = detail::_lock_helper(_m1, _m2, _m3, _m4);
1225 if (0 == _lock_first) return;
1226 break;
1227 case 1:
1228 _lock_first = detail::_lock_helper(_m2, _m3, _m4, _m1);
1229 if (0 == _lock_first) return;
1230 _lock_first = (_lock_first * 2) % _lock_count;
1231 break;
1232 case 2:
1233 _lock_first = detail::_lock_helper(_m3, _m4, _m1, _m2);
1234 if (0 == _lock_first) return;
1235 _lock_first = (_lock_first * 2) % _lock_count;
1236 break;
1237 case 3:
1238 _lock_first = detail::_lock_helper(_m4, _m1, _m2, _m3);
1239 if (0 == _lock_first) return;
1240 _lock_first = (_lock_first * 2) % _lock_count;
1241 break;
1242 }
1243 }
1244 }
1245
1246 template <class _Lockbl1, _STDEX_TYPES5>
1247 void lock(_Lockbl1 &_m1, _STDEX_ARGS5)
1248 {
1249 const unsigned int _lock_count = 5;
1250 unsigned int _lock_first = 0;
1251 for (;;)
1252 {
1253 switch (_lock_first)
1254 {
1255 case 0:
1256 _lock_first = detail::_lock_helper(_m1, _m2, _m3, _m4, _m5);
1257 if (0 == _lock_first) return;
1258 break;
1259 case 1:
1260 _lock_first = detail::_lock_helper(_m2, _m3, _m4, _m5, _m1);
1261 if (0 == _lock_first) return;
1262 _lock_first = (_lock_first * 2) % _lock_count;
1263 break;
1264 case 2:
1265 _lock_first = detail::_lock_helper(_m3, _m4, _m5, _m1, _m2);
1266 if (0 == _lock_first) return;
1267 _lock_first = (_lock_first * 2) % _lock_count;
1268 break;
1269 case 3:
1270 _lock_first = detail::_lock_helper(_m4, _m5, _m1, _m2, _m3);
1271 if (0 == _lock_first) return;
1272 _lock_first = (_lock_first * 2) % _lock_count;
1273 break;
1274 case 4:
1275 _lock_first = detail::_lock_helper(_m5, _m1, _m2, _m3, _m4);
1276 if (0 == _lock_first) return;
1277 _lock_first = (_lock_first * 2) % _lock_count;
1278 break;
1279 }
1280 }
1281 }
1282
1283 template <class _Lockbl1, _STDEX_TYPES6>
1284 void lock(_Lockbl1 &_m1, _STDEX_ARGS6)
1285 {
1286 const unsigned int _lock_count = 6;
1287 unsigned int _lock_first = 0;
1288 for (;;)
1289 {
1290 switch (_lock_first)
1291 {
1292 case 0:
1293 _lock_first = detail::_lock_helper(_m1, _m2, _m3, _m4, _m5, _m6);
1294 if (0 == _lock_first) return;
1295 break;
1296 case 1:
1297 _lock_first = detail::_lock_helper(_m2, _m3, _m4, _m5, _m6, _m1);
1298 if (0 == _lock_first) return;
1299 _lock_first = (_lock_first * 2) % _lock_count;
1300 break;
1301 case 2:
1302 _lock_first = detail::_lock_helper(_m3, _m4, _m5, _m6, _m1, _m2);
1303 if (0 == _lock_first) return;
1304 _lock_first = (_lock_first * 2) % _lock_count;
1305 break;
1306 case 3:
1307 _lock_first = detail::_lock_helper(_m4, _m5, _m6, _m1, _m2, _m3);
1308 if (0 == _lock_first) return;
1309 _lock_first = (_lock_first * 2) % _lock_count;
1310 break;
1311 case 4:
1312 _lock_first = detail::_lock_helper(_m5, _m6, _m1, _m2, _m3, _m4);
1313 if (0 == _lock_first) return;
1314 _lock_first = (_lock_first * 2) % _lock_count;
1315 break;
1316 case 5:
1317 _lock_first = detail::_lock_helper(_m6, _m1, _m2, _m3, _m4, _m5);
1318 if (0 == _lock_first) return;
1319 _lock_first = (_lock_first * 2) % _lock_count;
1320 break;
1321 }
1322 }
1323 }
1324
1325 template <class _Lockbl1, _STDEX_TYPES7>
1326 void lock(_Lockbl1 &_m1, _STDEX_ARGS7)
1327 {
1328 const unsigned int _lock_count = 7;
1329 unsigned int _lock_first = 0;
1330 for (;;)
1331 {
1332 switch (_lock_first)
1333 {
1334 case 0:
1335 _lock_first = detail::_lock_helper(_m1, _m2, _m3, _m4, _m5, _m6, _m7);
1336 if (0 == _lock_first) return;
1337 break;
1338 case 1:
1339 _lock_first = detail::_lock_helper(_m2, _m3, _m4, _m5, _m6, _m7, _m1);
1340 if (0 == _lock_first) return;
1341 _lock_first = (_lock_first * 2) % _lock_count;
1342 break;
1343 case 2:
1344 _lock_first = detail::_lock_helper(_m3, _m4, _m5, _m6, _m7, _m1, _m2);
1345 if (0 == _lock_first) return;
1346 _lock_first = (_lock_first * 2) % _lock_count;
1347 break;
1348 case 3:
1349 _lock_first = detail::_lock_helper(_m4, _m5, _m6, _m7, _m1, _m2, _m3);
1350 if (0 == _lock_first) return;
1351 _lock_first = (_lock_first * 2) % _lock_count;
1352 break;
1353 case 4:
1354 _lock_first = detail::_lock_helper(_m5, _m6, _m7, _m1, _m2, _m3, _m4);
1355 if (0 == _lock_first) return;
1356 _lock_first = (_lock_first * 2) % _lock_count;
1357 break;
1358 case 5:
1359 _lock_first = detail::_lock_helper(_m6, _m7, _m1, _m2, _m3, _m4, _m5);
1360 if (0 == _lock_first) return;
1361 _lock_first = (_lock_first * 2) % _lock_count;
1362 break;
1363 case 6:
1364 _lock_first = detail::_lock_helper(_m7, _m1, _m2, _m3, _m4, _m5, _m6);
1365 if (0 == _lock_first) return;
1366 _lock_first = (_lock_first * 2) % _lock_count;
1367 break;
1368 }
1369 }
1370 }
1371
1372 template <class _Lockbl1, _STDEX_TYPES8>
1373 void lock(_Lockbl1 &_m1, _STDEX_ARGS8)
1374 {
1375 const unsigned int _lock_count = 8;
1376 unsigned int _lock_first = 0;
1377 for (;;)
1378 {
1379 switch (_lock_first)
1380 {
1381 case 0:
1382 _lock_first = detail::_lock_helper(_m1, _m2, _m3, _m4, _m5, _m6, _m7, _m8);
1383 if (0 == _lock_first) return;
1384 break;
1385 case 1:
1386 _lock_first = detail::_lock_helper(_m2, _m3, _m4, _m5, _m6, _m7, _m8, _m1);
1387 if (0 == _lock_first) return;
1388 _lock_first = (_lock_first * 2) % _lock_count;
1389 break;
1390 case 2:
1391 _lock_first = detail::_lock_helper(_m3, _m4, _m5, _m6, _m7, _m8, _m1, _m2);
1392 if (0 == _lock_first) return;
1393 _lock_first = (_lock_first * 2) % _lock_count;
1394 break;
1395 case 3:
1396 _lock_first = detail::_lock_helper(_m4, _m5, _m6, _m7, _m8, _m1, _m2, _m3);
1397 if (0 == _lock_first) return;
1398 _lock_first = (_lock_first * 2) % _lock_count;
1399 break;
1400 case 4:
1401 _lock_first = detail::_lock_helper(_m5, _m6, _m7, _m8, _m1, _m2, _m3, _m4);
1402 if (0 == _lock_first) return;
1403 _lock_first = (_lock_first * 2) % _lock_count;
1404 break;
1405 case 5:
1406 _lock_first = detail::_lock_helper(_m6, _m7, _m8, _m1, _m2, _m3, _m4, _m5);
1407 if (0 == _lock_first) return;
1408 _lock_first = (_lock_first * 2) % _lock_count;
1409 break;
1410 case 6:
1411 _lock_first = detail::_lock_helper(_m7, _m8, _m1, _m2, _m3, _m4, _m5, _m6);
1412 if (0 == _lock_first) return;
1413 _lock_first = (_lock_first * 2) % _lock_count;
1414 break;
1415 case 7:
1416 _lock_first = detail::_lock_helper(_m8, _m1, _m2, _m3, _m4, _m5, _m6, _m7);
1417 if (0 == _lock_first) return;
1418 _lock_first = (_lock_first * 2) % _lock_count;
1419 break;
1420 }
1421 }
1422 }
1423
1424 template <class _Lockbl1, class _Lockbl2>
1425 int try_lock(_Lockbl1 &_m1, _Lockbl2 &_m2)
1426 {
1427 return detail::_try_lock_impl(_m1, _m2);
1428 }
1429
1430 template <class _Lockbl1, class _Lockbl2>
1431 int try_lock(const _Lockbl1 &_m1, _Lockbl2 &_m2)
1432 {
1433 return detail::_try_lock_impl(_m1, _m2);
1434 }
1435
1436 template <class _Lockbl1, class _Lockbl2>
1437 int try_lock(_Lockbl1 &_m1, const _Lockbl2 &_m2)
1438 {
1439 return detail::_try_lock_impl(_m1, _m2);
1440 }
1441
1442 template <class _Lockbl1, class _Lockbl2>
1443 int try_lock(const _Lockbl1 &_m1, const _Lockbl2 &_m2)
1444 {
1445 return detail::_try_lock_impl(_m1, _m2);
1446 }
1447
1448 using detail::try_lock;
1449
1450#undef _STDEX_TYPES_N
1451#undef _STDEX_ARGS_N
1452#undef _STDEX_ARGS_NAMES_N
1453
1454#undef _STDEX_TYPES3
1455#undef _STDEX_ARGS3
1456#undef _STDEX_ARGS_NAMES3
1457#undef _STDEX_TYPES4
1458#undef _STDEX_ARGS4
1459#undef _STDEX_ARGS_NAMES4
1460#undef _STDEX_TYPES5
1461#undef _STDEX_ARGS5
1462#undef _STDEX_ARGS_NAMES5
1463#undef _STDEX_TYPES6
1464#undef _STDEX_ARGS6
1465#undef _STDEX_ARGS_NAMES6
1466#undef _STDEX_TYPES7
1467#undef _STDEX_ARGS7
1468#undef _STDEX_ARGS_NAMES7
1469#undef _STDEX_TYPES8
1470#undef _STDEX_ARGS8
1471#undef _STDEX_ARGS_NAMES8
1472#undef _STDEX_TYPES9
1473#undef _STDEX_ARGS9
1474#undef _STDEX_ARGS_NAMES9
1475#undef _STDEX_TYPES10
1476#undef _STDEX_ARGS10
1477#undef _STDEX_ARGS_NAMES10
1478#undef _STDEX_TYPES11
1479#undef _STDEX_ARGS11
1480#undef _STDEX_ARGS_NAMES11
1481#undef _STDEX_TYPES12
1482#undef _STDEX_ARGS12
1483#undef _STDEX_ARGS_NAMES12
1484#undef _STDEX_TYPES13
1485#undef _STDEX_ARGS13
1486#undef _STDEX_ARGS_NAMES13
1487#undef _STDEX_TYPES14
1488#undef _STDEX_ARGS14
1489#undef _STDEX_ARGS_NAMES14
1490#undef _STDEX_TYPES15
1491#undef _STDEX_ARGS15
1492#undef _STDEX_ARGS_NAMES15
1493#undef _STDEX_TYPES16
1494#undef _STDEX_ARGS16
1495#undef _STDEX_ARGS_NAMES16
1496#undef _STDEX_TYPES17
1497#undef _STDEX_ARGS17
1498#undef _STDEX_ARGS_NAMES17
1499#undef _STDEX_TYPES18
1500#undef _STDEX_ARGS18
1501#undef _STDEX_ARGS_NAMES18
1502#undef _STDEX_TYPES19
1503#undef _STDEX_ARGS19
1504#undef _STDEX_ARGS_NAMES19
1505#undef _STDEX_TYPES20
1506#undef _STDEX_ARGS20
1507#undef _STDEX_ARGS_NAMES20
1508#undef _STDEX_TYPES21
1509#undef _STDEX_ARGS21
1510#undef _STDEX_ARGS_NAMES21
1511#undef _STDEX_TYPES22
1512#undef _STDEX_ARGS22
1513#undef _STDEX_ARGS_NAMES22
1514#undef _STDEX_TYPES23
1515#undef _STDEX_ARGS23
1516#undef _STDEX_ARGS_NAMES23
1517#undef _STDEX_TYPES24
1518#undef _STDEX_ARGS24
1519#undef _STDEX_ARGS_NAMES24
1520} // namespace stdex
1521
1522#undef _STDEX_DELETED_FUNCTION
1523#undef _STDEX_NOEXCEPT_FUNCTION
1524#undef _STDEX_NOEXCEPT
1525
1526
1527#endif // _STDEX_MUTEX_H
thread::id get_id()
Return the thread ID of the calling thread.