Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 22 additions & 2 deletions libcxx/include/shared_mutex
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ _LIBCPP_PUSH_MACROS

_LIBCPP_BEGIN_NAMESPACE_STD

struct _LIBCPP_EXPORTED_FROM_ABI __shared_mutex_base {
struct __dual_cv_shared_mutex {
mutex __mut_;
condition_variable __gate1_;
condition_variable __gate2_;
Expand All @@ -162,6 +162,26 @@ struct _LIBCPP_EXPORTED_FROM_ABI __shared_mutex_base {
static const unsigned __write_entered_ = 1U << (sizeof(unsigned) * __CHAR_BIT__ - 1);
static const unsigned __n_readers_ = ~__write_entered_;

_LIBCPP_HIDE_FROM_ABI __dual_cv_shared_mutex() : __state_(0) {}
_LIBCPP_HIDE_FROM_ABI ~__dual_cv_shared_mutex() = default;

__dual_cv_shared_mutex(const __dual_cv_shared_mutex&) = delete;
__dual_cv_shared_mutex& operator=(const __dual_cv_shared_mutex&) = delete;

// Exclusive ownership
_LIBCPP_HIDE_FROM_ABI void lock();
_LIBCPP_HIDE_FROM_ABI bool try_lock();
_LIBCPP_HIDE_FROM_ABI void unlock();

// Shared ownership
_LIBCPP_HIDE_FROM_ABI void lock_shared();
_LIBCPP_HIDE_FROM_ABI bool try_lock_shared();
_LIBCPP_HIDE_FROM_ABI void unlock_shared();
Comment on lines +171 to +179
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding _LIBCPP_HIDE_FROM_ABI to something that is implemented in the dylib like this feels very wrong. I also don't understand why we need to intoduce __dual_cv_shared_mutex. This seems like more effort than it's worth. We can just introduce a new __native_shared_mutex and keep the old __shared_mutex_base as the __dual_cv version. The naming might not be perfect, but we have to keep it around anyways, so I don't see how this improves anything.

};

struct _LIBCPP_EXPORTED_FROM_ABI __shared_mutex_base {
__dual_cv_shared_mutex __impl_;

__shared_mutex_base();
_LIBCPP_HIDE_FROM_ABI ~__shared_mutex_base() = default;

Expand Down Expand Up @@ -211,7 +231,7 @@ public:
# endif

class _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_CAPABILITY("shared_timed_mutex") shared_timed_mutex {
__shared_mutex_base __base_;
__dual_cv_shared_mutex __base_;

public:
shared_timed_mutex();
Expand Down
40 changes: 27 additions & 13 deletions libcxx/src/shared_mutex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,11 @@

_LIBCPP_BEGIN_NAMESPACE_STD

// Shared Mutex Base
__shared_mutex_base::__shared_mutex_base() : __state_(0) {}

// Exclusive ownership

void __shared_mutex_base::lock() {
// Dual condition_variable implementaiton of shared_mutex
//
// These methods are defined here because they're only called from the dylib,
// but they are not part of the library's ABI.
_LIBCPP_HIDE_FROM_ABI void __dual_cv_shared_mutex::lock() {
unique_lock<mutex> lk(__mut_);
while (__state_ & __write_entered_)
__gate1_.wait(lk);
Expand All @@ -28,7 +27,7 @@ void __shared_mutex_base::lock() {
__gate2_.wait(lk);
}

bool __shared_mutex_base::try_lock() {
_LIBCPP_HIDE_FROM_ABI bool __dual_cv_shared_mutex::try_lock() {
unique_lock<mutex> lk(__mut_);
if (__state_ == 0) {
__state_ = __write_entered_;
Expand All @@ -37,17 +36,15 @@ bool __shared_mutex_base::try_lock() {
return false;
}

void __shared_mutex_base::unlock() {
_LIBCPP_HIDE_FROM_ABI void __dual_cv_shared_mutex::unlock() {
{
lock_guard<mutex> _(__mut_);
__state_ = 0;
}
__gate1_.notify_all();
}

// Shared ownership

void __shared_mutex_base::lock_shared() {
_LIBCPP_HIDE_FROM_ABI void __dual_cv_shared_mutex::lock_shared() {
unique_lock<mutex> lk(__mut_);
while ((__state_ & __write_entered_) || (__state_ & __n_readers_) == __n_readers_)
__gate1_.wait(lk);
Expand All @@ -56,7 +53,7 @@ void __shared_mutex_base::lock_shared() {
__state_ |= num_readers;
}

bool __shared_mutex_base::try_lock_shared() {
_LIBCPP_HIDE_FROM_ABI bool __dual_cv_shared_mutex::try_lock_shared() {
unique_lock<mutex> lk(__mut_);
unsigned num_readers = __state_ & __n_readers_;
if (!(__state_ & __write_entered_) && num_readers != __n_readers_) {
Expand All @@ -68,7 +65,7 @@ bool __shared_mutex_base::try_lock_shared() {
return false;
}

void __shared_mutex_base::unlock_shared() {
_LIBCPP_HIDE_FROM_ABI void __dual_cv_shared_mutex::unlock_shared() {
unique_lock<mutex> lk(__mut_);
unsigned num_readers = (__state_ & __n_readers_) - 1;
__state_ &= ~__n_readers_;
Expand All @@ -86,6 +83,23 @@ void __shared_mutex_base::unlock_shared() {
}
}

// Shared Mutex Base
__shared_mutex_base::__shared_mutex_base() {}

// Exclusive ownership
void __shared_mutex_base::lock() { __impl_.lock(); }

bool __shared_mutex_base::try_lock() { return __impl_.try_lock(); }

void __shared_mutex_base::unlock() { __impl_.unlock(); }

// Shared ownership
void __shared_mutex_base::lock_shared() { __impl_.lock_shared(); }

bool __shared_mutex_base::try_lock_shared() { return __impl_.try_lock_shared(); }

void __shared_mutex_base::unlock_shared() { __impl_.unlock_shared(); }

// Shared Timed Mutex
// These routines are here for ABI stability
shared_timed_mutex::shared_timed_mutex() : __base_() {}
Expand Down
Loading