Project

General

Profile

Statistics
| Revision:

root / lab4 / .minix-src / include / c++ / __mutex_base

History | View | Annotate | Download (11.3 KB)

1 13 up20180614
// -*- C++ -*-
2
//===----------------------------------------------------------------------===//
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_BASE
12
#define _LIBCPP___MUTEX_BASE
13
14
#include <__config>
15
#include <chrono>
16
#include <system_error>
17
#include <pthread.h>
18
19
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
20
#pragma GCC system_header
21
#endif
22
23
_LIBCPP_BEGIN_NAMESPACE_STD
24
25
#ifndef _LIBCPP_HAS_NO_THREADS
26
27
class _LIBCPP_TYPE_VIS mutex
28
{
29
    pthread_mutex_t __m_;
30
31
public:
32
    _LIBCPP_INLINE_VISIBILITY
33
#ifndef _LIBCPP_HAS_NO_CONSTEXPR
34
     constexpr mutex() _NOEXCEPT : __m_(PTHREAD_MUTEX_INITIALIZER) {}
35
#else
36
     mutex() _NOEXCEPT {__m_ = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;}
37
#endif
38
     ~mutex();
39
40
private:
41
    mutex(const mutex&);// = delete;
42
    mutex& operator=(const mutex&);// = delete;
43
44
public:
45
    void lock();
46
    bool try_lock() _NOEXCEPT;
47
    void unlock() _NOEXCEPT;
48
49
    typedef pthread_mutex_t* native_handle_type;
50
    _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;}
51
};
52
53
struct _LIBCPP_TYPE_VIS defer_lock_t {};
54
struct _LIBCPP_TYPE_VIS try_to_lock_t {};
55
struct _LIBCPP_TYPE_VIS adopt_lock_t {};
56
57
#if defined(_LIBCPP_HAS_NO_CONSTEXPR) || defined(_LIBCPP_BUILDING_MUTEX)
58
59
extern const defer_lock_t  defer_lock;
60
extern const try_to_lock_t try_to_lock;
61
extern const adopt_lock_t  adopt_lock;
62
63
#else
64
65
constexpr defer_lock_t  defer_lock  = defer_lock_t();
66
constexpr try_to_lock_t try_to_lock = try_to_lock_t();
67
constexpr adopt_lock_t  adopt_lock  = adopt_lock_t();
68
69
#endif
70
71
template <class _Mutex>
72
class _LIBCPP_TYPE_VIS_ONLY lock_guard
73
{
74
public:
75
    typedef _Mutex mutex_type;
76
77
private:
78
    mutex_type& __m_;
79
public:
80
81
    _LIBCPP_INLINE_VISIBILITY
82
    explicit lock_guard(mutex_type& __m)
83
        : __m_(__m) {__m_.lock();}
84
    _LIBCPP_INLINE_VISIBILITY
85
    lock_guard(mutex_type& __m, adopt_lock_t)
86
        : __m_(__m) {}
87
    _LIBCPP_INLINE_VISIBILITY
88
    ~lock_guard() {__m_.unlock();}
89
90
private:
91
    lock_guard(lock_guard const&);// = delete;
92
    lock_guard& operator=(lock_guard const&);// = delete;
93
};
94
95
template <class _Mutex>
96
class _LIBCPP_TYPE_VIS_ONLY unique_lock
97
{
98
public:
99
    typedef _Mutex mutex_type;
100
101
private:
102
    mutex_type* __m_;
103
    bool __owns_;
104
105
public:
106
    _LIBCPP_INLINE_VISIBILITY
107
    unique_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {}
108
    _LIBCPP_INLINE_VISIBILITY
109
    explicit unique_lock(mutex_type& __m)
110
        : __m_(&__m), __owns_(true) {__m_->lock();}
111
    _LIBCPP_INLINE_VISIBILITY
112
    unique_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT
113
        : __m_(&__m), __owns_(false) {}
114
    _LIBCPP_INLINE_VISIBILITY
115
    unique_lock(mutex_type& __m, try_to_lock_t)
116
        : __m_(&__m), __owns_(__m.try_lock()) {}
117
    _LIBCPP_INLINE_VISIBILITY
118
    unique_lock(mutex_type& __m, adopt_lock_t)
119
        : __m_(&__m), __owns_(true) {}
120
    template <class _Clock, class _Duration>
121
    _LIBCPP_INLINE_VISIBILITY
122
        unique_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __t)
123
            : __m_(&__m), __owns_(__m.try_lock_until(__t)) {}
124
    template <class _Rep, class _Period>
125
    _LIBCPP_INLINE_VISIBILITY
126
        unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d)
127
            : __m_(&__m), __owns_(__m.try_lock_for(__d)) {}
128
    _LIBCPP_INLINE_VISIBILITY
129
    ~unique_lock()
130
    {
131
        if (__owns_)
132
            __m_->unlock();
133
    }
134
135
private:
136
    unique_lock(unique_lock const&); // = delete;
137
    unique_lock& operator=(unique_lock const&); // = delete;
138
139
public:
140
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
141
    _LIBCPP_INLINE_VISIBILITY
142
    unique_lock(unique_lock&& __u) _NOEXCEPT
143
        : __m_(__u.__m_), __owns_(__u.__owns_)
144
        {__u.__m_ = nullptr; __u.__owns_ = false;}
145
    _LIBCPP_INLINE_VISIBILITY
146
    unique_lock& operator=(unique_lock&& __u) _NOEXCEPT
147
        {
148
            if (__owns_)
149
                __m_->unlock();
150
            __m_ = __u.__m_;
151
            __owns_ = __u.__owns_;
152
            __u.__m_ = nullptr;
153
            __u.__owns_ = false;
154
            return *this;
155
        }
156
157
#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
158
159
    void lock();
160
    bool try_lock();
161
162
    template <class _Rep, class _Period>
163
        bool try_lock_for(const chrono::duration<_Rep, _Period>& __d);
164
    template <class _Clock, class _Duration>
165
        bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
166
167
    void unlock();
168
169
    _LIBCPP_INLINE_VISIBILITY
170
    void swap(unique_lock& __u) _NOEXCEPT
171
    {
172
        _VSTD::swap(__m_, __u.__m_);
173
        _VSTD::swap(__owns_, __u.__owns_);
174
    }
175
    _LIBCPP_INLINE_VISIBILITY
176
    mutex_type* release() _NOEXCEPT
177
    {
178
        mutex_type* __m = __m_;
179
        __m_ = nullptr;
180
        __owns_ = false;
181
        return __m;
182
    }
183
184
    _LIBCPP_INLINE_VISIBILITY
185
    bool owns_lock() const _NOEXCEPT {return __owns_;}
186
    _LIBCPP_INLINE_VISIBILITY
187
    _LIBCPP_EXPLICIT
188
        operator bool () const _NOEXCEPT {return __owns_;}
189
    _LIBCPP_INLINE_VISIBILITY
190
    mutex_type* mutex() const _NOEXCEPT {return __m_;}
191
};
192
193
template <class _Mutex>
194
void
195
unique_lock<_Mutex>::lock()
196
{
197
    if (__m_ == nullptr)
198
        __throw_system_error(EPERM, "unique_lock::lock: references null mutex");
199
    if (__owns_)
200
        __throw_system_error(EDEADLK, "unique_lock::lock: already locked");
201
    __m_->lock();
202
    __owns_ = true;
203
}
204
205
template <class _Mutex>
206
bool
207
unique_lock<_Mutex>::try_lock()
208
{
209
    if (__m_ == nullptr)
210
        __throw_system_error(EPERM, "unique_lock::try_lock: references null mutex");
211
    if (__owns_)
212
        __throw_system_error(EDEADLK, "unique_lock::try_lock: already locked");
213
    __owns_ = __m_->try_lock();
214
    return __owns_;
215
}
216
217
template <class _Mutex>
218
template <class _Rep, class _Period>
219
bool
220
unique_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d)
221
{
222
    if (__m_ == nullptr)
223
        __throw_system_error(EPERM, "unique_lock::try_lock_for: references null mutex");
224
    if (__owns_)
225
        __throw_system_error(EDEADLK, "unique_lock::try_lock_for: already locked");
226
    __owns_ = __m_->try_lock_for(__d);
227
    return __owns_;
228
}
229
230
template <class _Mutex>
231
template <class _Clock, class _Duration>
232
bool
233
unique_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
234
{
235
    if (__m_ == nullptr)
236
        __throw_system_error(EPERM, "unique_lock::try_lock_until: references null mutex");
237
    if (__owns_)
238
        __throw_system_error(EDEADLK, "unique_lock::try_lock_until: already locked");
239
    __owns_ = __m_->try_lock_until(__t);
240
    return __owns_;
241
}
242
243
template <class _Mutex>
244
void
245
unique_lock<_Mutex>::unlock()
246
{
247
    if (!__owns_)
248
        __throw_system_error(EPERM, "unique_lock::unlock: not locked");
249
    __m_->unlock();
250
    __owns_ = false;
251
}
252
253
template <class _Mutex>
254
inline _LIBCPP_INLINE_VISIBILITY
255
void
256
swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) _NOEXCEPT
257
    {__x.swap(__y);}
258
259
//enum class cv_status
260
_LIBCPP_DECLARE_STRONG_ENUM(cv_status)
261
{
262
    no_timeout,
263
    timeout
264
};
265
_LIBCPP_DECLARE_STRONG_ENUM_EPILOG(cv_status)
266
267
class _LIBCPP_TYPE_VIS condition_variable
268
{
269
    pthread_cond_t __cv_;
270
public:
271
    _LIBCPP_INLINE_VISIBILITY
272
#ifndef _LIBCPP_HAS_NO_CONSTEXPR
273
    constexpr condition_variable() : __cv_(PTHREAD_COND_INITIALIZER) {}
274
#else
275
    condition_variable() {__cv_ = (pthread_cond_t)PTHREAD_COND_INITIALIZER;}
276
#endif
277
    ~condition_variable();
278
279
private:
280
    condition_variable(const condition_variable&); // = delete;
281
    condition_variable& operator=(const condition_variable&); // = delete;
282
283
public:
284
    void notify_one() _NOEXCEPT;
285
    void notify_all() _NOEXCEPT;
286
287
    void wait(unique_lock<mutex>& __lk) _NOEXCEPT;
288
    template <class _Predicate>
289
        void wait(unique_lock<mutex>& __lk, _Predicate __pred);
290
291
    template <class _Clock, class _Duration>
292
        cv_status
293
        wait_until(unique_lock<mutex>& __lk,
294
                   const chrono::time_point<_Clock, _Duration>& __t);
295
296
    template <class _Clock, class _Duration, class _Predicate>
297
        bool
298
        wait_until(unique_lock<mutex>& __lk,
299
                   const chrono::time_point<_Clock, _Duration>& __t,
300
                   _Predicate __pred);
301
302
    template <class _Rep, class _Period>
303
        cv_status
304
        wait_for(unique_lock<mutex>& __lk,
305
                 const chrono::duration<_Rep, _Period>& __d);
306
307
    template <class _Rep, class _Period, class _Predicate>
308
        bool
309
        wait_for(unique_lock<mutex>& __lk,
310
                 const chrono::duration<_Rep, _Period>& __d,
311
                 _Predicate __pred);
312
313
    typedef pthread_cond_t* native_handle_type;
314
    _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__cv_;}
315
316
private:
317
    void __do_timed_wait(unique_lock<mutex>& __lk,
318
       chrono::time_point<chrono::system_clock, chrono::nanoseconds>) _NOEXCEPT;
319
};
320
#endif // !_LIBCPP_HAS_NO_THREADS
321
322
template <class _To, class _Rep, class _Period>
323
inline _LIBCPP_INLINE_VISIBILITY
324
typename enable_if
325
<
326
    chrono::__is_duration<_To>::value,
327
    _To
328
>::type
329
__ceil(chrono::duration<_Rep, _Period> __d)
330
{
331
    using namespace chrono;
332
    _To __r = duration_cast<_To>(__d);
333
    if (__r < __d)
334
        ++__r;
335
    return __r;
336
}
337
338
#ifndef _LIBCPP_HAS_NO_THREADS
339
template <class _Predicate>
340
void
341
condition_variable::wait(unique_lock<mutex>& __lk, _Predicate __pred)
342
{
343
    while (!__pred())
344
        wait(__lk);
345
}
346
347
template <class _Clock, class _Duration>
348
cv_status
349
condition_variable::wait_until(unique_lock<mutex>& __lk,
350
                               const chrono::time_point<_Clock, _Duration>& __t)
351
{
352
    using namespace chrono;
353
    wait_for(__lk, __t - _Clock::now());
354
    return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout;
355
}
356
357
template <class _Clock, class _Duration, class _Predicate>
358
bool
359
condition_variable::wait_until(unique_lock<mutex>& __lk,
360
                   const chrono::time_point<_Clock, _Duration>& __t,
361
                   _Predicate __pred)
362
{
363
    while (!__pred())
364
    {
365
        if (wait_until(__lk, __t) == cv_status::timeout)
366
            return __pred();
367
    }
368
    return true;
369
}
370
371
template <class _Rep, class _Period>
372
cv_status
373
condition_variable::wait_for(unique_lock<mutex>& __lk,
374
                             const chrono::duration<_Rep, _Period>& __d)
375
{
376
    using namespace chrono;
377
    if (__d <= __d.zero())
378
        return cv_status::timeout;
379
    typedef time_point<system_clock, duration<long double, nano> > __sys_tpf;
380
    typedef time_point<system_clock, nanoseconds> __sys_tpi;
381
    __sys_tpf _Max = __sys_tpi::max();
382
    system_clock::time_point __s_now = system_clock::now();
383
    steady_clock::time_point __c_now = steady_clock::now();
384
    if (_Max - __d > __s_now)
385
        __do_timed_wait(__lk, __s_now + __ceil<nanoseconds>(__d));
386
    else
387
        __do_timed_wait(__lk, __sys_tpi::max());
388
    return steady_clock::now() - __c_now < __d ? cv_status::no_timeout :
389
                                                 cv_status::timeout;
390
}
391
392
template <class _Rep, class _Period, class _Predicate>
393
inline _LIBCPP_INLINE_VISIBILITY
394
bool
395
condition_variable::wait_for(unique_lock<mutex>& __lk,
396
                             const chrono::duration<_Rep, _Period>& __d,
397
                             _Predicate __pred)
398
{
399
    return wait_until(__lk, chrono::steady_clock::now() + __d,
400
                      _VSTD::move(__pred));
401
}
402
403
#endif // !_LIBCPP_HAS_NO_THREADS
404
405
_LIBCPP_END_NAMESPACE_STD
406
407
#endif  // _LIBCPP___MUTEX_BASE