Project

General

Profile

Statistics
| Revision:

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

History | View | Annotate | Download (13.9 KB)

1 13 up20180614
// -*- C++ -*-
2
//===------------------------ shared_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_SHARED_MUTEX
12
#define _LIBCPP_SHARED_MUTEX
13
14
/*
15
    shared_mutex synopsis
16
17
// C++1y
18
19
namespace std
20
{
21
22
class shared_mutex      // C++17
23
{
24
public:
25
    shared_mutex();
26
    ~shared_mutex();
27
28
    shared_mutex(const shared_mutex&) = delete;
29
    shared_mutex& operator=(const shared_mutex&) = delete;
30
31
    // Exclusive ownership
32
    void lock(); // blocking
33
    bool try_lock();
34
    void unlock();
35
36
    // Shared ownership
37
    void lock_shared(); // blocking
38
    bool try_lock_shared();
39
    void unlock_shared();
40
41
    typedef implementation-defined native_handle_type; // See 30.2.3
42
    native_handle_type native_handle(); // See 30.2.3
43
};
44
45
class shared_timed_mutex
46
{
47
public:
48
    shared_timed_mutex();
49
    ~shared_timed_mutex();
50
51
    shared_timed_mutex(const shared_timed_mutex&) = delete;
52
    shared_timed_mutex& operator=(const shared_timed_mutex&) = delete;
53
54
    // Exclusive ownership
55
    void lock(); // blocking
56
    bool try_lock();
57
    template <class Rep, class Period>
58
        bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
59
    template <class Clock, class Duration>
60
        bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
61
    void unlock();
62
63
    // Shared ownership
64
    void lock_shared(); // blocking
65
    bool try_lock_shared();
66
    template <class Rep, class Period>
67
        bool
68
        try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time);
69
    template <class Clock, class Duration>
70
        bool
71
        try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time);
72
    void unlock_shared();
73
};
74
75
template <class Mutex>
76
class shared_lock
77
{
78
public:
79
    typedef Mutex mutex_type;
80
81
    // Shared locking
82
    shared_lock() noexcept;
83
    explicit shared_lock(mutex_type& m); // blocking
84
    shared_lock(mutex_type& m, defer_lock_t) noexcept;
85
    shared_lock(mutex_type& m, try_to_lock_t);
86
    shared_lock(mutex_type& m, adopt_lock_t);
87
    template <class Clock, class Duration>
88
        shared_lock(mutex_type& m,
89
                    const chrono::time_point<Clock, Duration>& abs_time);
90
    template <class Rep, class Period>
91
        shared_lock(mutex_type& m,
92
                    const chrono::duration<Rep, Period>& rel_time);
93
    ~shared_lock();
94
95
    shared_lock(shared_lock const&) = delete;
96
    shared_lock& operator=(shared_lock const&) = delete;
97
98
    shared_lock(shared_lock&& u) noexcept;
99
    shared_lock& operator=(shared_lock&& u) noexcept;
100
101
    void lock(); // blocking
102
    bool try_lock();
103
    template <class Rep, class Period>
104
        bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
105
    template <class Clock, class Duration>
106
        bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
107
    void unlock();
108
109
    // Setters
110
    void swap(shared_lock& u) noexcept;
111
    mutex_type* release() noexcept;
112
113
    // Getters
114
    bool owns_lock() const noexcept;
115
    explicit operator bool () const noexcept;
116
    mutex_type* mutex() const noexcept;
117
};
118
119
template <class Mutex>
120
    void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
121
122
}  // std
123
124
*/
125
126
#include <__config>
127
128
#if _LIBCPP_STD_VER > 11 || defined(_LIBCPP_BUILDING_SHARED_MUTEX)
129
130
#include <__mutex_base>
131
132
#include <__undef_min_max>
133
134
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
135
#pragma GCC system_header
136
#endif
137
138
#ifdef _LIBCPP_HAS_NO_THREADS
139
#error <shared_mutex> is not supported on this single threaded system
140
#else // !_LIBCPP_HAS_NO_THREADS
141
142
_LIBCPP_BEGIN_NAMESPACE_STD
143
144
struct _LIBCPP_TYPE_VIS __shared_mutex_base
145
{
146
    mutex               __mut_;
147
    condition_variable  __gate1_;
148
    condition_variable  __gate2_;
149
    unsigned            __state_;
150
151
    static const unsigned __write_entered_ = 1U << (sizeof(unsigned)*__CHAR_BIT__ - 1);
152
    static const unsigned __n_readers_ = ~__write_entered_;
153
154
    __shared_mutex_base();
155
    _LIBCPP_INLINE_VISIBILITY ~__shared_mutex_base() = default;
156
157
    __shared_mutex_base(const __shared_mutex_base&) = delete;
158
    __shared_mutex_base& operator=(const __shared_mutex_base&) = delete;
159
160
    // Exclusive ownership
161
    void lock(); // blocking
162
    bool try_lock();
163
    void unlock();
164
165
    // Shared ownership
166
    void lock_shared(); // blocking
167
    bool try_lock_shared();
168
    void unlock_shared();
169
170
//     typedef implementation-defined native_handle_type; // See 30.2.3
171
//     native_handle_type native_handle(); // See 30.2.3
172
};
173
174
175
#if _LIBCPP_STD_VER > 14
176
class _LIBCPP_TYPE_VIS shared_mutex
177
{
178
	__shared_mutex_base __base;
179
public:
180
    shared_mutex() : __base() {}
181
    _LIBCPP_INLINE_VISIBILITY ~shared_mutex() = default;
182
183
    shared_mutex(const shared_mutex&) = delete;
184
    shared_mutex& operator=(const shared_mutex&) = delete;
185
186
    // Exclusive ownership
187
    _LIBCPP_INLINE_VISIBILITY void lock()     { return __base.lock(); }
188
    _LIBCPP_INLINE_VISIBILITY bool try_lock() { return __base.try_lock(); }
189
    _LIBCPP_INLINE_VISIBILITY void unlock()   { return __base.unlock(); }
190
191
    // Shared ownership
192
    _LIBCPP_INLINE_VISIBILITY void lock_shared()     { return __base.lock_shared(); }
193
    _LIBCPP_INLINE_VISIBILITY bool try_lock_shared() { return __base.try_lock_shared(); }
194
    _LIBCPP_INLINE_VISIBILITY void unlock_shared()   { return __base.unlock_shared(); }
195
196
//     typedef __shared_mutex_base::native_handle_type native_handle_type;
197
//     _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() { return __base::unlock_shared(); }
198
};
199
#endif
200
201
202
class _LIBCPP_TYPE_VIS shared_timed_mutex
203
{
204
	__shared_mutex_base __base;
205
public:
206
    shared_timed_mutex();
207
    _LIBCPP_INLINE_VISIBILITY ~shared_timed_mutex() = default;
208
209
    shared_timed_mutex(const shared_timed_mutex&) = delete;
210
    shared_timed_mutex& operator=(const shared_timed_mutex&) = delete;
211
212
    // Exclusive ownership
213
    void lock();
214
    bool try_lock();
215
    template <class _Rep, class _Period>
216
        _LIBCPP_INLINE_VISIBILITY
217
        bool
218
        try_lock_for(const chrono::duration<_Rep, _Period>& __rel_time)
219
        {
220
            return try_lock_until(chrono::steady_clock::now() + __rel_time);
221
        }
222
    template <class _Clock, class _Duration>
223
        bool
224
        try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time);
225
    void unlock();
226
227
    // Shared ownership
228
    void lock_shared();
229
    bool try_lock_shared();
230
    template <class _Rep, class _Period>
231
        _LIBCPP_INLINE_VISIBILITY
232
        bool
233
        try_lock_shared_for(const chrono::duration<_Rep, _Period>& __rel_time)
234
        {
235
            return try_lock_shared_until(chrono::steady_clock::now() + __rel_time);
236
        }
237
    template <class _Clock, class _Duration>
238
        bool
239
        try_lock_shared_until(const chrono::time_point<_Clock, _Duration>& __abs_time);
240
    void unlock_shared();
241
};
242
243
template <class _Clock, class _Duration>
244
bool
245
shared_timed_mutex::try_lock_until(
246
                        const chrono::time_point<_Clock, _Duration>& __abs_time)
247
{
248
    unique_lock<mutex> __lk(__base.__mut_);
249
    if (__base.__state_ & __base.__write_entered_)
250
    {
251
        while (true)
252
        {
253
            cv_status __status = __base.__gate1_.wait_until(__lk, __abs_time);
254
            if ((__base.__state_ & __base.__write_entered_) == 0)
255
                break;
256
            if (__status == cv_status::timeout)
257
                return false;
258
        }
259
    }
260
    __base.__state_ |= __base.__write_entered_;
261
    if (__base.__state_ & __base.__n_readers_)
262
    {
263
        while (true)
264
        {
265
            cv_status __status = __base.__gate2_.wait_until(__lk, __abs_time);
266
            if ((__base.__state_ & __base.__n_readers_) == 0)
267
                break;
268
            if (__status == cv_status::timeout)
269
            {
270
                __base.__state_ &= ~__base.__write_entered_;
271
                __base.__gate1_.notify_all();
272
                return false;
273
            }
274
        }
275
    }
276
    return true;
277
}
278
279
template <class _Clock, class _Duration>
280
bool
281
shared_timed_mutex::try_lock_shared_until(
282
                        const chrono::time_point<_Clock, _Duration>& __abs_time)
283
{
284
    unique_lock<mutex> __lk(__base.__mut_);
285
    if ((__base.__state_ & __base.__write_entered_) || (__base.__state_ & __base.__n_readers_) == __base.__n_readers_)
286
    {
287
        while (true)
288
        {
289
            cv_status status = __base.__gate1_.wait_until(__lk, __abs_time);
290
            if ((__base.__state_ & __base.__write_entered_) == 0 &&
291
                                       (__base.__state_ & __base.__n_readers_) < __base.__n_readers_)
292
                break;
293
            if (status == cv_status::timeout)
294
                return false;
295
        }
296
    }
297
    unsigned __num_readers = (__base.__state_ & __base.__n_readers_) + 1;
298
    __base.__state_ &= ~__base.__n_readers_;
299
    __base.__state_ |= __num_readers;
300
    return true;
301
}
302
303
template <class _Mutex>
304
class shared_lock
305
{
306
public:
307
    typedef _Mutex mutex_type;
308
309
private:
310
    mutex_type* __m_;
311
    bool __owns_;
312
313
public:
314
    _LIBCPP_INLINE_VISIBILITY
315
    shared_lock() _NOEXCEPT
316
        : __m_(nullptr),
317
          __owns_(false)
318
        {}
319
320
    _LIBCPP_INLINE_VISIBILITY
321
    explicit shared_lock(mutex_type& __m)
322
        : __m_(&__m),
323
          __owns_(true)
324
        {__m_->lock_shared();}
325
326
    _LIBCPP_INLINE_VISIBILITY
327
    shared_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT
328
        : __m_(&__m),
329
          __owns_(false)
330
        {}
331
332
    _LIBCPP_INLINE_VISIBILITY
333
    shared_lock(mutex_type& __m, try_to_lock_t)
334
        : __m_(&__m),
335
          __owns_(__m.try_lock_shared())
336
        {}
337
338
    _LIBCPP_INLINE_VISIBILITY
339
    shared_lock(mutex_type& __m, adopt_lock_t)
340
        : __m_(&__m),
341
          __owns_(true)
342
        {}
343
344
    template <class _Clock, class _Duration>
345
        _LIBCPP_INLINE_VISIBILITY
346
        shared_lock(mutex_type& __m,
347
                    const chrono::time_point<_Clock, _Duration>& __abs_time)
348
            : __m_(&__m),
349
              __owns_(__m.try_lock_shared_until(__abs_time))
350
            {}
351
352
    template <class _Rep, class _Period>
353
        _LIBCPP_INLINE_VISIBILITY
354
        shared_lock(mutex_type& __m,
355
                    const chrono::duration<_Rep, _Period>& __rel_time)
356
            : __m_(&__m),
357
              __owns_(__m.try_lock_shared_for(__rel_time))
358
            {}
359
360
    _LIBCPP_INLINE_VISIBILITY
361
    ~shared_lock()
362
    {
363
        if (__owns_)
364
            __m_->unlock_shared();
365
    }
366
367
    shared_lock(shared_lock const&) = delete;
368
    shared_lock& operator=(shared_lock const&) = delete;
369
370
    _LIBCPP_INLINE_VISIBILITY
371
    shared_lock(shared_lock&& __u) _NOEXCEPT
372
        : __m_(__u.__m_),
373
          __owns_(__u.__owns_)
374
        {
375
            __u.__m_ = nullptr;
376
            __u.__owns_ = false;
377
        }
378
379
    _LIBCPP_INLINE_VISIBILITY
380
    shared_lock& operator=(shared_lock&& __u) _NOEXCEPT
381
    {
382
        if (__owns_)
383
            __m_->unlock_shared();
384
        __m_ = nullptr;
385
        __owns_ = false;
386
        __m_ = __u.__m_;
387
        __owns_ = __u.__owns_;
388
        __u.__m_ = nullptr;
389
        __u.__owns_ = false;
390
        return *this;
391
    }
392
393
    void lock();
394
    bool try_lock();
395
    template <class Rep, class Period>
396
        bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
397
    template <class Clock, class Duration>
398
        bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
399
    void unlock();
400
401
    // Setters
402
    _LIBCPP_INLINE_VISIBILITY
403
    void swap(shared_lock& __u) _NOEXCEPT
404
    {
405
        _VSTD::swap(__m_, __u.__m_);
406
        _VSTD::swap(__owns_, __u.__owns_);
407
    }
408
409
    _LIBCPP_INLINE_VISIBILITY
410
    mutex_type* release() _NOEXCEPT
411
    {
412
        mutex_type* __m = __m_;
413
        __m_ = nullptr;
414
        __owns_ = false;
415
        return __m;
416
    }
417
418
    // Getters
419
    _LIBCPP_INLINE_VISIBILITY
420
    bool owns_lock() const _NOEXCEPT {return __owns_;}
421
422
    _LIBCPP_INLINE_VISIBILITY
423
    explicit operator bool () const _NOEXCEPT {return __owns_;}
424
425
    _LIBCPP_INLINE_VISIBILITY
426
    mutex_type* mutex() const _NOEXCEPT {return __m_;}
427
};
428
429
template <class _Mutex>
430
void
431
shared_lock<_Mutex>::lock()
432
{
433
    if (__m_ == nullptr)
434
        __throw_system_error(EPERM, "shared_lock::lock: references null mutex");
435
    if (__owns_)
436
        __throw_system_error(EDEADLK, "shared_lock::lock: already locked");
437
    __m_->lock_shared();
438
    __owns_ = true;
439
}
440
441
template <class _Mutex>
442
bool
443
shared_lock<_Mutex>::try_lock()
444
{
445
    if (__m_ == nullptr)
446
        __throw_system_error(EPERM, "shared_lock::try_lock: references null mutex");
447
    if (__owns_)
448
        __throw_system_error(EDEADLK, "shared_lock::try_lock: already locked");
449
    __owns_ = __m_->try_lock_shared();
450
    return __owns_;
451
}
452
453
template <class _Mutex>
454
template <class _Rep, class _Period>
455
bool
456
shared_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d)
457
{
458
    if (__m_ == nullptr)
459
        __throw_system_error(EPERM, "shared_lock::try_lock_for: references null mutex");
460
    if (__owns_)
461
        __throw_system_error(EDEADLK, "shared_lock::try_lock_for: already locked");
462
    __owns_ = __m_->try_lock_shared_for(__d);
463
    return __owns_;
464
}
465
466
template <class _Mutex>
467
template <class _Clock, class _Duration>
468
bool
469
shared_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
470
{
471
    if (__m_ == nullptr)
472
        __throw_system_error(EPERM, "shared_lock::try_lock_until: references null mutex");
473
    if (__owns_)
474
        __throw_system_error(EDEADLK, "shared_lock::try_lock_until: already locked");
475
    __owns_ = __m_->try_lock_shared_until(__t);
476
    return __owns_;
477
}
478
479
template <class _Mutex>
480
void
481
shared_lock<_Mutex>::unlock()
482
{
483
    if (!__owns_)
484
        __throw_system_error(EPERM, "shared_lock::unlock: not locked");
485
    __m_->unlock_shared();
486
    __owns_ = false;
487
}
488
489
template <class _Mutex>
490
inline _LIBCPP_INLINE_VISIBILITY
491
void
492
swap(shared_lock<_Mutex>& __x, shared_lock<_Mutex>& __y) _NOEXCEPT
493
    {__x.swap(__y);}
494
495
_LIBCPP_END_NAMESPACE_STD
496
497
#endif  // !_LIBCPP_HAS_NO_THREADS
498
499
#endif  // _LIBCPP_STD_VER > 11
500
501
#endif  // _LIBCPP_SHARED_MUTEX