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 #include "shared_mutex"
     14 
     15 _LIBCPP_BEGIN_NAMESPACE_STD
     16 
     17 // Shared Mutex Base
     18 __shared_mutex_base::__shared_mutex_base()
     19     : __state_(0)
     20 {
     21 }
     22 
     23 // Exclusive ownership
     24 
     25 void
     26 __shared_mutex_base::lock()
     27 {
     28     unique_lock<mutex> lk(__mut_);
     29     while (__state_ & __write_entered_)
     30         __gate1_.wait(lk);
     31     __state_ |= __write_entered_;
     32     while (__state_ & __n_readers_)
     33         __gate2_.wait(lk);
     34 }
     35 
     36 bool
     37 __shared_mutex_base::try_lock()
     38 {
     39     unique_lock<mutex> lk(__mut_);
     40     if (__state_ == 0)
     41     {
     42         __state_ = __write_entered_;
     43         return true;
     44     }
     45     return false;
     46 }
     47 
     48 void
     49 __shared_mutex_base::unlock()
     50 {
     51     lock_guard<mutex> _(__mut_);
     52     __state_ = 0;
     53     __gate1_.notify_all();
     54 }
     55 
     56 // Shared ownership
     57 
     58 void
     59 __shared_mutex_base::lock_shared()
     60 {
     61     unique_lock<mutex> lk(__mut_);
     62     while ((__state_ & __write_entered_) || (__state_ & __n_readers_) == __n_readers_)
     63         __gate1_.wait(lk);
     64     unsigned num_readers = (__state_ & __n_readers_) + 1;
     65     __state_ &= ~__n_readers_;
     66     __state_ |= num_readers;
     67 }
     68 
     69 bool
     70 __shared_mutex_base::try_lock_shared()
     71 {
     72     unique_lock<mutex> lk(__mut_);
     73     unsigned num_readers = __state_ & __n_readers_;
     74     if (!(__state_ & __write_entered_) && num_readers != __n_readers_)
     75     {
     76         ++num_readers;
     77         __state_ &= ~__n_readers_;
     78         __state_ |= num_readers;
     79         return true;
     80     }
     81     return false;
     82 }
     83 
     84 void
     85 __shared_mutex_base::unlock_shared()
     86 {
     87     lock_guard<mutex> _(__mut_);
     88     unsigned num_readers = (__state_ & __n_readers_) - 1;
     89     __state_ &= ~__n_readers_;
     90     __state_ |= num_readers;
     91     if (__state_ & __write_entered_)
     92     {
     93         if (num_readers == 0)
     94             __gate2_.notify_one();
     95     }
     96     else
     97     {
     98         if (num_readers == __n_readers_ - 1)
     99             __gate1_.notify_one();
    100     }
    101 }
    102 
    103 
    104 // Shared Timed Mutex
    105 // These routines are here for ABI stability
    106 shared_timed_mutex::shared_timed_mutex() : __base() {}
    107 void shared_timed_mutex::lock()     { return __base.lock(); }
    108 bool shared_timed_mutex::try_lock() { return __base.try_lock(); }
    109 void shared_timed_mutex::unlock()   { return __base.unlock(); }
    110 void shared_timed_mutex::lock_shared() { return __base.lock_shared(); }
    111 bool shared_timed_mutex::try_lock_shared() { return __base.try_lock_shared(); }
    112 void shared_timed_mutex::unlock_shared() { return __base.unlock_shared(); }
    113 
    114 _LIBCPP_END_NAMESPACE_STD
    115 
    116 #endif // !_LIBCPP_HAS_NO_THREADS
    117