Home | History | Annotate | Download | only in src
      1 //===---------------------- shared_mutex.cpp ------------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is dual licensed under the MIT and the University of Illinois Open
      6 // Source Licenses. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "__config"
     11 #ifndef _LIBCPP_HAS_NO_THREADS
     12 
     13 #define _LIBCPP_BUILDING_SHARED_MUTEX
     14 #include "shared_mutex"
     15 
     16 _LIBCPP_BEGIN_NAMESPACE_STD
     17 
     18 // Shared Mutex Base
     19 __shared_mutex_base::__shared_mutex_base()
     20     : __state_(0)
     21 {
     22 }
     23 
     24 // Exclusive ownership
     25 
     26 void
     27 __shared_mutex_base::lock()
     28 {
     29     unique_lock<mutex> lk(__mut_);
     30     while (__state_ & __write_entered_)
     31         __gate1_.wait(lk);
     32     __state_ |= __write_entered_;
     33     while (__state_ & __n_readers_)
     34         __gate2_.wait(lk);
     35 }
     36 
     37 bool
     38 __shared_mutex_base::try_lock()
     39 {
     40     unique_lock<mutex> lk(__mut_);
     41     if (__state_ == 0)
     42     {
     43         __state_ = __write_entered_;
     44         return true;
     45     }
     46     return false;
     47 }
     48 
     49 void
     50 __shared_mutex_base::unlock()
     51 {
     52     lock_guard<mutex> _(__mut_);
     53     __state_ = 0;
     54     __gate1_.notify_all();
     55 }
     56 
     57 // Shared ownership
     58 
     59 void
     60 __shared_mutex_base::lock_shared()
     61 {
     62     unique_lock<mutex> lk(__mut_);
     63     while ((__state_ & __write_entered_) || (__state_ & __n_readers_) == __n_readers_)
     64         __gate1_.wait(lk);
     65     unsigned num_readers = (__state_ & __n_readers_) + 1;
     66     __state_ &= ~__n_readers_;
     67     __state_ |= num_readers;
     68 }
     69 
     70 bool
     71 __shared_mutex_base::try_lock_shared()
     72 {
     73     unique_lock<mutex> lk(__mut_);
     74     unsigned num_readers = __state_ & __n_readers_;
     75     if (!(__state_ & __write_entered_) && num_readers != __n_readers_)
     76     {
     77         ++num_readers;
     78         __state_ &= ~__n_readers_;
     79         __state_ |= num_readers;
     80         return true;
     81     }
     82     return false;
     83 }
     84 
     85 void
     86 __shared_mutex_base::unlock_shared()
     87 {
     88     lock_guard<mutex> _(__mut_);
     89     unsigned num_readers = (__state_ & __n_readers_) - 1;
     90     __state_ &= ~__n_readers_;
     91     __state_ |= num_readers;
     92     if (__state_ & __write_entered_)
     93     {
     94         if (num_readers == 0)
     95             __gate2_.notify_one();
     96     }
     97     else
     98     {
     99         if (num_readers == __n_readers_ - 1)
    100             __gate1_.notify_one();
    101     }
    102 }
    103 
    104 
    105 // Shared Timed Mutex
    106 // These routines are here for ABI stability
    107 shared_timed_mutex::shared_timed_mutex() : __base() {}
    108 void shared_timed_mutex::lock()     { return __base.lock(); }
    109 bool shared_timed_mutex::try_lock() { return __base.try_lock(); }
    110 void shared_timed_mutex::unlock()   { return __base.unlock(); }
    111 void shared_timed_mutex::lock_shared() { return __base.lock_shared(); }
    112 bool shared_timed_mutex::try_lock_shared() { return __base.try_lock_shared(); }
    113 void shared_timed_mutex::unlock_shared() { return __base.unlock_shared(); }
    114 
    115 _LIBCPP_END_NAMESPACE_STD
    116 
    117 #endif // !_LIBCPP_HAS_NO_THREADS
    118