~ubuntu-branches/ubuntu/saucy/emscripten/saucy-proposed

« back to all changes in this revision

Viewing changes to system/include/libcxx/mutex

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2013-05-02 13:11:51 UTC
  • Revision ID: package-import@ubuntu.com-20130502131151-q8dvteqr1ef2x7xz
Tags: upstream-1.4.1~20130504~adb56cb
ImportĀ upstreamĀ versionĀ 1.4.1~20130504~adb56cb

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// -*- C++ -*-
 
2
//===--------------------------- mutex ------------------------------------===//
 
3
//
 
4
//                     The LLVM Compiler Infrastructure
 
5
//
 
6
// This file is dual licensed under the MIT and the University of Illinois Open
 
7
// Source Licenses. See LICENSE.TXT for details.
 
8
//
 
9
//===----------------------------------------------------------------------===//
 
10
 
 
11
#ifndef _LIBCPP_MUTEX
 
12
#define _LIBCPP_MUTEX
 
13
 
 
14
/*
 
15
    mutex synopsis
 
16
 
 
17
namespace std
 
18
{
 
19
 
 
20
class mutex
 
21
{
 
22
public:
 
23
     constexpr mutex() noexcept;
 
24
     ~mutex();
 
25
 
 
26
    mutex(const mutex&) = delete;
 
27
    mutex& operator=(const mutex&) = delete;
 
28
 
 
29
    void lock();
 
30
    bool try_lock();
 
31
    void unlock();
 
32
 
 
33
    typedef pthread_mutex_t* native_handle_type;
 
34
    native_handle_type native_handle();
 
35
};
 
36
 
 
37
class recursive_mutex
 
38
{
 
39
public:
 
40
     recursive_mutex();
 
41
     ~recursive_mutex();
 
42
 
 
43
    recursive_mutex(const recursive_mutex&) = delete;
 
44
    recursive_mutex& operator=(const recursive_mutex&) = delete;
 
45
 
 
46
    void lock();
 
47
    bool try_lock() noexcept;
 
48
    void unlock();
 
49
 
 
50
    typedef pthread_mutex_t* native_handle_type;
 
51
    native_handle_type native_handle();
 
52
};
 
53
 
 
54
class timed_mutex
 
55
{
 
56
public:
 
57
     timed_mutex();
 
58
     ~timed_mutex();
 
59
 
 
60
    timed_mutex(const timed_mutex&) = delete;
 
61
    timed_mutex& operator=(const timed_mutex&) = delete;
 
62
 
 
63
    void lock();
 
64
    bool try_lock();
 
65
    template <class Rep, class Period>
 
66
        bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
 
67
    template <class Clock, class Duration>
 
68
        bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
 
69
    void unlock();
 
70
};
 
71
 
 
72
class recursive_timed_mutex
 
73
{
 
74
public:
 
75
     recursive_timed_mutex();
 
76
     ~recursive_timed_mutex();
 
77
 
 
78
    recursive_timed_mutex(const recursive_timed_mutex&) = delete;
 
79
    recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
 
80
 
 
81
    void lock();
 
82
    bool try_lock() noexcept;
 
83
    template <class Rep, class Period>
 
84
        bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
 
85
    template <class Clock, class Duration>
 
86
        bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
 
87
    void unlock();
 
88
};
 
89
 
 
90
struct defer_lock_t {};
 
91
struct try_to_lock_t {};
 
92
struct adopt_lock_t {};
 
93
 
 
94
constexpr defer_lock_t  defer_lock{};
 
95
constexpr try_to_lock_t try_to_lock{};
 
96
constexpr adopt_lock_t  adopt_lock{};
 
97
 
 
98
template <class Mutex>
 
99
class lock_guard
 
100
{
 
101
public:
 
102
    typedef Mutex mutex_type;
 
103
 
 
104
    explicit lock_guard(mutex_type& m);
 
105
    lock_guard(mutex_type& m, adopt_lock_t);
 
106
    ~lock_guard();
 
107
 
 
108
    lock_guard(lock_guard const&) = delete;
 
109
    lock_guard& operator=(lock_guard const&) = delete;
 
110
};
 
111
 
 
112
template <class Mutex>
 
113
class unique_lock
 
114
{
 
115
public:
 
116
    typedef Mutex mutex_type;
 
117
    unique_lock() noexcept;
 
118
    explicit unique_lock(mutex_type& m);
 
119
    unique_lock(mutex_type& m, defer_lock_t) noexcept;
 
120
    unique_lock(mutex_type& m, try_to_lock_t);
 
121
    unique_lock(mutex_type& m, adopt_lock_t);
 
122
    template <class Clock, class Duration>
 
123
        unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time);
 
124
    template <class Rep, class Period>
 
125
        unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time);
 
126
    ~unique_lock();
 
127
 
 
128
    unique_lock(unique_lock const&) = delete;
 
129
    unique_lock& operator=(unique_lock const&) = delete;
 
130
 
 
131
    unique_lock(unique_lock&& u) noexcept;
 
132
    unique_lock& operator=(unique_lock&& u) noexcept;
 
133
 
 
134
    void lock();
 
135
    bool try_lock();
 
136
 
 
137
    template <class Rep, class Period>
 
138
        bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
 
139
    template <class Clock, class Duration>
 
140
        bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
 
141
 
 
142
    void unlock();
 
143
 
 
144
    void swap(unique_lock& u) noexcept;
 
145
    mutex_type* release() noexcept;
 
146
 
 
147
    bool owns_lock() const noexcept;
 
148
    explicit operator bool () const noexcept;
 
149
    mutex_type* mutex() const noexcept;
 
150
};
 
151
 
 
152
template <class Mutex>
 
153
  void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
 
154
 
 
155
template <class L1, class L2, class... L3>
 
156
  int try_lock(L1&, L2&, L3&...);
 
157
template <class L1, class L2, class... L3>
 
158
  void lock(L1&, L2&, L3&...);
 
159
 
 
160
struct once_flag
 
161
{
 
162
    constexpr once_flag() noexcept;
 
163
 
 
164
    once_flag(const once_flag&) = delete;
 
165
    once_flag& operator=(const once_flag&) = delete;
 
166
};
 
167
 
 
168
template<class Callable, class ...Args>
 
169
  void call_once(once_flag& flag, Callable&& func, Args&&... args);
 
170
 
 
171
}  // std
 
172
 
 
173
*/
 
174
 
 
175
#include <__config>
 
176
#include <__mutex_base>
 
177
#include <functional>
 
178
#ifndef _LIBCPP_HAS_NO_VARIADICS
 
179
#include <tuple>
 
180
#endif
 
181
 
 
182
#include <__undef_min_max>
 
183
 
 
184
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 
185
#pragma GCC system_header
 
186
#endif
 
187
 
 
188
_LIBCPP_BEGIN_NAMESPACE_STD
 
189
 
 
190
class _LIBCPP_TYPE_VIS recursive_mutex
 
191
{
 
192
    pthread_mutex_t __m_;
 
193
 
 
194
public:
 
195
     recursive_mutex();
 
196
     ~recursive_mutex();
 
197
 
 
198
private:
 
199
    recursive_mutex(const recursive_mutex&); // = delete;
 
200
    recursive_mutex& operator=(const recursive_mutex&); // = delete;
 
201
 
 
202
public:
 
203
    void lock();
 
204
    bool try_lock() _NOEXCEPT;
 
205
    void unlock()  _NOEXCEPT;
 
206
 
 
207
    typedef pthread_mutex_t* native_handle_type;
 
208
    _LIBCPP_INLINE_VISIBILITY
 
209
    native_handle_type native_handle() {return &__m_;}
 
210
};
 
211
 
 
212
class _LIBCPP_TYPE_VIS timed_mutex
 
213
{
 
214
    mutex              __m_;
 
215
    condition_variable __cv_;
 
216
    bool               __locked_;
 
217
public:
 
218
     timed_mutex();
 
219
     ~timed_mutex();
 
220
 
 
221
private:
 
222
    timed_mutex(const timed_mutex&); // = delete;
 
223
    timed_mutex& operator=(const timed_mutex&); // = delete;
 
224
 
 
225
public:
 
226
    void lock();
 
227
    bool try_lock() _NOEXCEPT;
 
228
    template <class _Rep, class _Period>
 
229
        _LIBCPP_INLINE_VISIBILITY
 
230
        bool try_lock_for(const chrono::duration<_Rep, _Period>& __d)
 
231
            {return try_lock_until(chrono::steady_clock::now() + __d);}
 
232
    template <class _Clock, class _Duration>
 
233
        bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
 
234
    void unlock() _NOEXCEPT;
 
235
};
 
236
 
 
237
template <class _Clock, class _Duration>
 
238
bool
 
239
timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
 
240
{
 
241
    using namespace chrono;
 
242
    unique_lock<mutex> __lk(__m_);
 
243
    bool no_timeout = _Clock::now() < __t;
 
244
    while (no_timeout && __locked_)
 
245
        no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout;
 
246
    if (!__locked_)
 
247
    {
 
248
        __locked_ = true;
 
249
        return true;
 
250
    }
 
251
    return false;
 
252
}
 
253
 
 
254
class _LIBCPP_TYPE_VIS recursive_timed_mutex
 
255
{
 
256
    mutex              __m_;
 
257
    condition_variable __cv_;
 
258
    size_t             __count_;
 
259
    pthread_t          __id_;
 
260
public:
 
261
     recursive_timed_mutex();
 
262
     ~recursive_timed_mutex();
 
263
 
 
264
private:
 
265
    recursive_timed_mutex(const recursive_timed_mutex&); // = delete;
 
266
    recursive_timed_mutex& operator=(const recursive_timed_mutex&); // = delete;
 
267
 
 
268
public:
 
269
    void lock();
 
270
    bool try_lock() _NOEXCEPT;
 
271
    template <class _Rep, class _Period>
 
272
        _LIBCPP_INLINE_VISIBILITY
 
273
        bool try_lock_for(const chrono::duration<_Rep, _Period>& __d)
 
274
            {return try_lock_until(chrono::steady_clock::now() + __d);}
 
275
    template <class _Clock, class _Duration>
 
276
        bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
 
277
    void unlock() _NOEXCEPT;
 
278
};
 
279
 
 
280
template <class _Clock, class _Duration>
 
281
bool
 
282
recursive_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
 
283
{
 
284
    using namespace chrono;
 
285
    pthread_t __id = pthread_self();
 
286
    unique_lock<mutex> lk(__m_);
 
287
    if (pthread_equal(__id, __id_))
 
288
    {
 
289
        if (__count_ == numeric_limits<size_t>::max())
 
290
            return false;
 
291
        ++__count_;
 
292
        return true;
 
293
    }
 
294
    bool no_timeout = _Clock::now() < __t;
 
295
    while (no_timeout && __count_ != 0)
 
296
        no_timeout = __cv_.wait_until(lk, __t) == cv_status::no_timeout;
 
297
    if (__count_ == 0)
 
298
    {
 
299
        __count_ = 1;
 
300
        __id_ = __id;
 
301
        return true;
 
302
    }
 
303
    return false;
 
304
}
 
305
 
 
306
template <class _L0, class _L1>
 
307
int
 
308
try_lock(_L0& __l0, _L1& __l1)
 
309
{
 
310
    unique_lock<_L0> __u0(__l0, try_to_lock);
 
311
    if (__u0.owns_lock())
 
312
    {
 
313
        if (__l1.try_lock())
 
314
        {
 
315
            __u0.release();
 
316
            return -1;
 
317
        }
 
318
        else
 
319
            return 1;
 
320
    }
 
321
    return 0;
 
322
}
 
323
 
 
324
#ifndef _LIBCPP_HAS_NO_VARIADICS
 
325
 
 
326
template <class _L0, class _L1, class _L2, class... _L3>
 
327
int
 
328
try_lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3)
 
329
{
 
330
    int __r = 0;
 
331
    unique_lock<_L0> __u0(__l0, try_to_lock);
 
332
    if (__u0.owns_lock())
 
333
    {
 
334
        __r = try_lock(__l1, __l2, __l3...);
 
335
        if (__r == -1)
 
336
            __u0.release();
 
337
        else
 
338
            ++__r;
 
339
    }
 
340
    return __r;
 
341
}
 
342
 
 
343
#endif  // _LIBCPP_HAS_NO_VARIADICS
 
344
 
 
345
template <class _L0, class _L1>
 
346
void
 
347
lock(_L0& __l0, _L1& __l1)
 
348
{
 
349
    while (true)
 
350
    {
 
351
        {
 
352
            unique_lock<_L0> __u0(__l0);
 
353
            if (__l1.try_lock())
 
354
            {
 
355
                __u0.release();
 
356
                break;
 
357
            }
 
358
        }
 
359
        sched_yield();
 
360
        {
 
361
            unique_lock<_L1> __u1(__l1);
 
362
            if (__l0.try_lock())
 
363
            {
 
364
                __u1.release();
 
365
                break;
 
366
            }
 
367
        }
 
368
        sched_yield();
 
369
    }
 
370
}
 
371
 
 
372
#ifndef _LIBCPP_HAS_NO_VARIADICS
 
373
 
 
374
template <class _L0, class _L1, class _L2, class ..._L3>
 
375
void
 
376
__lock_first(int __i, _L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3)
 
377
{
 
378
    while (true)
 
379
    {
 
380
        switch (__i)
 
381
        {
 
382
        case 0:
 
383
            {
 
384
                unique_lock<_L0> __u0(__l0);
 
385
                __i = try_lock(__l1, __l2, __l3...);
 
386
                if (__i == -1)
 
387
                {
 
388
                    __u0.release();
 
389
                    return;
 
390
                }
 
391
            }
 
392
            ++__i;
 
393
            sched_yield();
 
394
            break;
 
395
        case 1:
 
396
            {
 
397
                unique_lock<_L1> __u1(__l1);
 
398
                __i = try_lock(__l2, __l3..., __l0);
 
399
                if (__i == -1)
 
400
                {
 
401
                    __u1.release();
 
402
                    return;
 
403
                }
 
404
            }
 
405
            if (__i == sizeof...(_L3) + 1)
 
406
                __i = 0;
 
407
            else
 
408
                __i += 2;
 
409
            sched_yield();
 
410
            break;
 
411
        default:
 
412
            __lock_first(__i - 2, __l2, __l3..., __l0, __l1);
 
413
            return;
 
414
        }
 
415
    }
 
416
}
 
417
 
 
418
template <class _L0, class _L1, class _L2, class ..._L3>
 
419
inline _LIBCPP_INLINE_VISIBILITY
 
420
void
 
421
lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3)
 
422
{
 
423
    __lock_first(0, __l0, __l1, __l2, __l3...);
 
424
}
 
425
 
 
426
#endif  // _LIBCPP_HAS_NO_VARIADICS
 
427
 
 
428
struct _LIBCPP_TYPE_VIS once_flag;
 
429
 
 
430
#ifndef _LIBCPP_HAS_NO_VARIADICS
 
431
 
 
432
template<class _Callable, class... _Args>
 
433
_LIBCPP_INLINE_VISIBILITY
 
434
void call_once(once_flag&, _Callable&&, _Args&&...);
 
435
 
 
436
#else  // _LIBCPP_HAS_NO_VARIADICS
 
437
 
 
438
template<class _Callable>
 
439
_LIBCPP_INLINE_VISIBILITY
 
440
void call_once(once_flag&, _Callable);
 
441
 
 
442
#endif  // _LIBCPP_HAS_NO_VARIADICS
 
443
 
 
444
struct _LIBCPP_TYPE_VIS once_flag
 
445
{
 
446
    _LIBCPP_INLINE_VISIBILITY
 
447
    _LIBCPP_CONSTEXPR
 
448
        once_flag() _NOEXCEPT : __state_(0) {}
 
449
 
 
450
private:
 
451
    once_flag(const once_flag&); // = delete;
 
452
    once_flag& operator=(const once_flag&); // = delete;
 
453
 
 
454
    unsigned long __state_;
 
455
 
 
456
#ifndef _LIBCPP_HAS_NO_VARIADICS
 
457
    template<class _Callable, class... _Args>
 
458
    friend
 
459
    void call_once(once_flag&, _Callable&&, _Args&&...);
 
460
#else  // _LIBCPP_HAS_NO_VARIADICS
 
461
    template<class _Callable>
 
462
    friend
 
463
    void call_once(once_flag&, _Callable);
 
464
#endif  // _LIBCPP_HAS_NO_VARIADICS
 
465
};
 
466
 
 
467
#ifndef _LIBCPP_HAS_NO_VARIADICS
 
468
 
 
469
template <class _Fp>
 
470
class __call_once_param
 
471
{
 
472
    _Fp __f_;
 
473
public:
 
474
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
 
475
    _LIBCPP_INLINE_VISIBILITY
 
476
    explicit __call_once_param(_Fp&& __f) : __f_(_VSTD::move(__f)) {}
 
477
#else
 
478
    _LIBCPP_INLINE_VISIBILITY
 
479
    explicit __call_once_param(const _Fp& __f) : __f_(__f) {}
 
480
#endif
 
481
 
 
482
    _LIBCPP_INLINE_VISIBILITY
 
483
    void operator()()
 
484
    {
 
485
        typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 1>::type _Index;
 
486
        __execute(_Index());
 
487
    }
 
488
 
 
489
private:
 
490
    template <size_t ..._Indices>
 
491
    _LIBCPP_INLINE_VISIBILITY
 
492
    void __execute(__tuple_indices<_Indices...>)
 
493
    {
 
494
        __invoke(_VSTD::move(_VSTD::get<0>(__f_)), _VSTD::move(_VSTD::get<_Indices>(__f_))...);
 
495
    }
 
496
};
 
497
 
 
498
#else
 
499
 
 
500
template <class _Fp>
 
501
class __call_once_param
 
502
{
 
503
    _Fp __f_;
 
504
public:
 
505
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
 
506
    _LIBCPP_INLINE_VISIBILITY
 
507
    explicit __call_once_param(_Fp&& __f) : __f_(_VSTD::move(__f)) {}
 
508
#else
 
509
    _LIBCPP_INLINE_VISIBILITY
 
510
    explicit __call_once_param(const _Fp& __f) : __f_(__f) {}
 
511
#endif
 
512
 
 
513
    _LIBCPP_INLINE_VISIBILITY
 
514
    void operator()()
 
515
    {
 
516
        __f_();
 
517
    }
 
518
};
 
519
 
 
520
#endif
 
521
 
 
522
template <class _Fp>
 
523
void
 
524
__call_once_proxy(void* __vp)
 
525
{
 
526
    __call_once_param<_Fp>* __p = static_cast<__call_once_param<_Fp>*>(__vp);
 
527
    (*__p)();
 
528
}
 
529
 
 
530
void __call_once(volatile unsigned long&, void*, void(*)(void*));
 
531
 
 
532
#ifndef _LIBCPP_HAS_NO_VARIADICS
 
533
 
 
534
template<class _Callable, class... _Args>
 
535
inline _LIBCPP_INLINE_VISIBILITY
 
536
void
 
537
call_once(once_flag& __flag, _Callable&& __func, _Args&&... __args)
 
538
{
 
539
    if (__flag.__state_ != ~0ul)
 
540
    {
 
541
        typedef tuple<typename decay<_Callable>::type, typename decay<_Args>::type...> _Gp;
 
542
        __call_once_param<_Gp> __p(_Gp(__decay_copy(_VSTD::forward<_Callable>(__func)),
 
543
                                __decay_copy(_VSTD::forward<_Args>(__args))...));
 
544
        __call_once(__flag.__state_, &__p, &__call_once_proxy<_Gp>);
 
545
    }
 
546
}
 
547
 
 
548
#else  // _LIBCPP_HAS_NO_VARIADICS
 
549
 
 
550
template<class _Callable>
 
551
inline _LIBCPP_INLINE_VISIBILITY
 
552
void
 
553
call_once(once_flag& __flag, _Callable __func)
 
554
{
 
555
    if (__flag.__state_ != ~0ul)
 
556
    {
 
557
        __call_once_param<_Callable> __p(__func);
 
558
        __call_once(__flag.__state_, &__p, &__call_once_proxy<_Callable>);
 
559
    }
 
560
}
 
561
 
 
562
#endif  // _LIBCPP_HAS_NO_VARIADICS
 
563
 
 
564
_LIBCPP_END_NAMESPACE_STD
 
565
 
 
566
#endif  // _LIBCPP_MUTEX