Project

General

Profile

Statistics
| Revision:

root / lab4 / .minix-src / include / c++ / mutex @ 14

History | View | Annotate | Download (13.8 KB)

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
#if !defined(_LIBCPP_HAS_NO_THREADS) && defined(__minix)
177
#include <__mutex_base>
178
#endif // !defined(_LIBCPP_HAS_NO_THREADS) && defined(__minix)
179
#include <functional>
180
#include <memory>
181
#ifndef _LIBCPP_HAS_NO_VARIADICS
182
#include <tuple>
183
#endif
184
#include <sched.h>
185

    
186
#include <__undef_min_max>
187

    
188
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
189
#pragma GCC system_header
190
#endif
191

    
192
_LIBCPP_BEGIN_NAMESPACE_STD
193

    
194
#ifndef _LIBCPP_HAS_NO_THREADS
195

    
196
class _LIBCPP_TYPE_VIS recursive_mutex
197
{
198
    pthread_mutex_t __m_;
199

    
200
public:
201
     recursive_mutex();
202
     ~recursive_mutex();
203

    
204
private:
205
    recursive_mutex(const recursive_mutex&); // = delete;
206
    recursive_mutex& operator=(const recursive_mutex&); // = delete;
207

    
208
public:
209
    void lock();
210
    bool try_lock() _NOEXCEPT;
211
    void unlock()  _NOEXCEPT;
212

    
213
    typedef pthread_mutex_t* native_handle_type;
214
    _LIBCPP_INLINE_VISIBILITY
215
    native_handle_type native_handle() {return &__m_;}
216
};
217

    
218
class _LIBCPP_TYPE_VIS timed_mutex
219
{
220
    mutex              __m_;
221
    condition_variable __cv_;
222
    bool               __locked_;
223
public:
224
     timed_mutex();
225
     ~timed_mutex();
226

    
227
private:
228
    timed_mutex(const timed_mutex&); // = delete;
229
    timed_mutex& operator=(const timed_mutex&); // = delete;
230

    
231
public:
232
    void lock();
233
    bool try_lock() _NOEXCEPT;
234
    template <class _Rep, class _Period>
235
        _LIBCPP_INLINE_VISIBILITY
236
        bool try_lock_for(const chrono::duration<_Rep, _Period>& __d)
237
            {return try_lock_until(chrono::steady_clock::now() + __d);}
238
    template <class _Clock, class _Duration>
239
        bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
240
    void unlock() _NOEXCEPT;
241
};
242

    
243
template <class _Clock, class _Duration>
244
bool
245
timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
246
{
247
    using namespace chrono;
248
    unique_lock<mutex> __lk(__m_);
249
    bool no_timeout = _Clock::now() < __t;
250
    while (no_timeout && __locked_)
251
        no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout;
252
    if (!__locked_)
253
    {
254
        __locked_ = true;
255
        return true;
256
    }
257
    return false;
258
}
259

    
260
class _LIBCPP_TYPE_VIS recursive_timed_mutex
261
{
262
    mutex              __m_;
263
    condition_variable __cv_;
264
    size_t             __count_;
265
    pthread_t          __id_;
266
public:
267
     recursive_timed_mutex();
268
     ~recursive_timed_mutex();
269

    
270
private:
271
    recursive_timed_mutex(const recursive_timed_mutex&); // = delete;
272
    recursive_timed_mutex& operator=(const recursive_timed_mutex&); // = delete;
273

    
274
public:
275
    void lock();
276
    bool try_lock() _NOEXCEPT;
277
    template <class _Rep, class _Period>
278
        _LIBCPP_INLINE_VISIBILITY
279
        bool try_lock_for(const chrono::duration<_Rep, _Period>& __d)
280
            {return try_lock_until(chrono::steady_clock::now() + __d);}
281
    template <class _Clock, class _Duration>
282
        bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
283
    void unlock() _NOEXCEPT;
284
};
285

    
286
template <class _Clock, class _Duration>
287
bool
288
recursive_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
289
{
290
    using namespace chrono;
291
    pthread_t __id = pthread_self();
292
    unique_lock<mutex> lk(__m_);
293
    if (pthread_equal(__id, __id_))
294
    {
295
        if (__count_ == numeric_limits<size_t>::max())
296
            return false;
297
        ++__count_;
298
        return true;
299
    }
300
    bool no_timeout = _Clock::now() < __t;
301
    while (no_timeout && __count_ != 0)
302
        no_timeout = __cv_.wait_until(lk, __t) == cv_status::no_timeout;
303
    if (__count_ == 0)
304
    {
305
        __count_ = 1;
306
        __id_ = __id;
307
        return true;
308
    }
309
    return false;
310
}
311

    
312
template <class _L0, class _L1>
313
int
314
try_lock(_L0& __l0, _L1& __l1)
315
{
316
    unique_lock<_L0> __u0(__l0, try_to_lock);
317
    if (__u0.owns_lock())
318
    {
319
        if (__l1.try_lock())
320
        {
321
            __u0.release();
322
            return -1;
323
        }
324
        else
325
            return 1;
326
    }
327
    return 0;
328
}
329

    
330
#ifndef _LIBCPP_HAS_NO_VARIADICS
331

    
332
template <class _L0, class _L1, class _L2, class... _L3>
333
int
334
try_lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3)
335
{
336
    int __r = 0;
337
    unique_lock<_L0> __u0(__l0, try_to_lock);
338
    if (__u0.owns_lock())
339
    {
340
        __r = try_lock(__l1, __l2, __l3...);
341
        if (__r == -1)
342
            __u0.release();
343
        else
344
            ++__r;
345
    }
346
    return __r;
347
}
348

    
349
#endif  // _LIBCPP_HAS_NO_VARIADICS
350

    
351
template <class _L0, class _L1>
352
void
353
lock(_L0& __l0, _L1& __l1)
354
{
355
    while (true)
356
    {
357
        {
358
            unique_lock<_L0> __u0(__l0);
359
            if (__l1.try_lock())
360
            {
361
                __u0.release();
362
                break;
363
            }
364
        }
365
        sched_yield();
366
        {
367
            unique_lock<_L1> __u1(__l1);
368
            if (__l0.try_lock())
369
            {
370
                __u1.release();
371
                break;
372
            }
373
        }
374
        sched_yield();
375
    }
376
}
377

    
378
#ifndef _LIBCPP_HAS_NO_VARIADICS
379

    
380
template <class _L0, class _L1, class _L2, class ..._L3>
381
void
382
__lock_first(int __i, _L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3)
383
{
384
    while (true)
385
    {
386
        switch (__i)
387
        {
388
        case 0:
389
            {
390
                unique_lock<_L0> __u0(__l0);
391
                __i = try_lock(__l1, __l2, __l3...);
392
                if (__i == -1)
393
                {
394
                    __u0.release();
395
                    return;
396
                }
397
            }
398
            ++__i;
399
            sched_yield();
400
            break;
401
        case 1:
402
            {
403
                unique_lock<_L1> __u1(__l1);
404
                __i = try_lock(__l2, __l3..., __l0);
405
                if (__i == -1)
406
                {
407
                    __u1.release();
408
                    return;
409
                }
410
            }
411
            if (__i == sizeof...(_L3) + 1)
412
                __i = 0;
413
            else
414
                __i += 2;
415
            sched_yield();
416
            break;
417
        default:
418
            __lock_first(__i - 2, __l2, __l3..., __l0, __l1);
419
            return;
420
        }
421
    }
422
}
423

    
424
template <class _L0, class _L1, class _L2, class ..._L3>
425
inline _LIBCPP_INLINE_VISIBILITY
426
void
427
lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3)
428
{
429
    __lock_first(0, __l0, __l1, __l2, __l3...);
430
}
431

    
432
#endif  // _LIBCPP_HAS_NO_VARIADICS
433

    
434
#endif // !_LIBCPP_HAS_NO_THREADS
435

    
436
struct _LIBCPP_TYPE_VIS_ONLY once_flag;
437

    
438
#ifndef _LIBCPP_HAS_NO_VARIADICS
439

    
440
template<class _Callable, class... _Args>
441
_LIBCPP_INLINE_VISIBILITY
442
void call_once(once_flag&, _Callable&&, _Args&&...);
443

    
444
#else  // _LIBCPP_HAS_NO_VARIADICS
445

    
446
template<class _Callable>
447
_LIBCPP_INLINE_VISIBILITY
448
void call_once(once_flag&, _Callable&);
449

    
450
template<class _Callable>
451
_LIBCPP_INLINE_VISIBILITY
452
void call_once(once_flag&, const _Callable&);
453

    
454
#endif  // _LIBCPP_HAS_NO_VARIADICS
455

    
456
struct _LIBCPP_TYPE_VIS_ONLY once_flag
457
{
458
    _LIBCPP_INLINE_VISIBILITY
459
    _LIBCPP_CONSTEXPR
460
        once_flag() _NOEXCEPT : __state_(0) {}
461

    
462
private:
463
    once_flag(const once_flag&); // = delete;
464
    once_flag& operator=(const once_flag&); // = delete;
465

    
466
    unsigned long __state_;
467

    
468
#ifndef _LIBCPP_HAS_NO_VARIADICS
469
    template<class _Callable, class... _Args>
470
    friend
471
    void call_once(once_flag&, _Callable&&, _Args&&...);
472
#else  // _LIBCPP_HAS_NO_VARIADICS
473
    template<class _Callable>
474
    friend
475
    void call_once(once_flag&, _Callable&);
476

    
477
    template<class _Callable>
478
    friend
479
    void call_once(once_flag&, const _Callable&);
480
#endif  // _LIBCPP_HAS_NO_VARIADICS
481
};
482

    
483
#ifndef _LIBCPP_HAS_NO_VARIADICS
484

    
485
template <class _Fp>
486
class __call_once_param
487
{
488
    _Fp& __f_;
489
public:
490
    _LIBCPP_INLINE_VISIBILITY
491
    explicit __call_once_param(_Fp& __f) : __f_(__f) {}
492

    
493
    _LIBCPP_INLINE_VISIBILITY
494
    void operator()()
495
    {
496
        typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 1>::type _Index;
497
        __execute(_Index());
498
    }
499

    
500
private:
501
    template <size_t ..._Indices>
502
    _LIBCPP_INLINE_VISIBILITY
503
    void __execute(__tuple_indices<_Indices...>)
504
    {
505
        __invoke(_VSTD::get<0>(_VSTD::move(__f_)), _VSTD::get<_Indices>(_VSTD::move(__f_))...);
506
    }
507
};
508

    
509
#else
510

    
511
template <class _Fp>
512
class __call_once_param
513
{
514
    _Fp& __f_;
515
public:
516
    _LIBCPP_INLINE_VISIBILITY
517
    explicit __call_once_param(_Fp& __f) : __f_(__f) {}
518

    
519
    _LIBCPP_INLINE_VISIBILITY
520
    void operator()()
521
    {
522
        __f_();
523
    }
524
};
525

    
526
#endif
527

    
528
template <class _Fp>
529
void
530
__call_once_proxy(void* __vp)
531
{
532
    __call_once_param<_Fp>* __p = static_cast<__call_once_param<_Fp>*>(__vp);
533
    (*__p)();
534
}
535

    
536
_LIBCPP_FUNC_VIS void __call_once(volatile unsigned long&, void*, void(*)(void*));
537

    
538
#ifndef _LIBCPP_HAS_NO_VARIADICS
539

    
540
template<class _Callable, class... _Args>
541
inline _LIBCPP_INLINE_VISIBILITY
542
void
543
call_once(once_flag& __flag, _Callable&& __func, _Args&&... __args)
544
{
545
    if (__libcpp_relaxed_load(&__flag.__state_) != ~0ul)
546
    {
547
        typedef tuple<_Callable&&, _Args&&...> _Gp;
548
        _Gp __f(_VSTD::forward<_Callable>(__func), _VSTD::forward<_Args>(__args)...);
549
        __call_once_param<_Gp> __p(__f);
550
        __call_once(__flag.__state_, &__p, &__call_once_proxy<_Gp>);
551
    }
552
}
553

    
554
#else  // _LIBCPP_HAS_NO_VARIADICS
555

    
556
template<class _Callable>
557
inline _LIBCPP_INLINE_VISIBILITY
558
void
559
call_once(once_flag& __flag, _Callable& __func)
560
{
561
    if (__libcpp_relaxed_load(&__flag.__state_) != ~0ul)
562
    {
563
        __call_once_param<_Callable> __p(__func);
564
        __call_once(__flag.__state_, &__p, &__call_once_proxy<_Callable>);
565
    }
566
}
567

    
568
template<class _Callable>
569
inline _LIBCPP_INLINE_VISIBILITY
570
void
571
call_once(once_flag& __flag, const _Callable& __func)
572
{
573
    if (__flag.__state_ != ~0ul)
574
    {
575
        __call_once_param<const _Callable> __p(__func);
576
        __call_once(__flag.__state_, &__p, &__call_once_proxy<const _Callable>);
577
    }
578
}
579

    
580
#endif  // _LIBCPP_HAS_NO_VARIADICS
581

    
582
_LIBCPP_END_NAMESPACE_STD
583

    
584
#endif  // _LIBCPP_MUTEX