diff --git a/include/asyncpp/lock.hpp b/include/asyncpp/lock.hpp index eb81972..e8f48bf 100644 --- a/include/asyncpp/lock.hpp +++ b/include/asyncpp/lock.hpp @@ -8,104 +8,99 @@ namespace asyncpp { -template -class locked_mutex { + +template +class basic_locked_mutex { friend Mutex; public: - locked_mutex(locked_mutex&&) = default; - locked_mutex& operator=(locked_mutex&&) = default; - locked_mutex(const locked_mutex&) = delete; - locked_mutex& operator=(const locked_mutex&) = delete; + basic_locked_mutex(basic_locked_mutex&&) = default; + basic_locked_mutex& operator=(basic_locked_mutex&&) = default; + basic_locked_mutex(const basic_locked_mutex&) = delete; + basic_locked_mutex& operator=(const basic_locked_mutex&) = delete; Mutex& mutex() const noexcept { return *m_mtx; } + static constexpr bool shared() noexcept { + return Shared; + } + private: - locked_mutex(Mutex* mtx) : m_mtx(mtx) {} + basic_locked_mutex(Mutex* mtx) : m_mtx(mtx) {} Mutex* m_mtx = nullptr; }; template -class locked_mutex_shared { - friend Mutex; +using exclusively_locked_mutex = basic_locked_mutex; +template +using shared_locked_mutex = basic_locked_mutex; -public: - locked_mutex_shared(locked_mutex_shared&&) = default; - locked_mutex_shared& operator=(locked_mutex_shared&&) = default; - locked_mutex_shared(const locked_mutex_shared&) = delete; - locked_mutex_shared& operator=(const locked_mutex_shared&) = delete; - Mutex& mutex() const noexcept { - return *m_mtx; - } -private: - locked_mutex_shared(Mutex* mtx) : m_mtx(mtx) {} - Mutex* m_mtx = nullptr; -}; +template +class basic_lock { + // NOTE: GCC bugs out on `auto (Mutex::*Lock)()`, that's why `Lock` is simply `auto`. + using mutex_awaitable_t = std::invoke_result_t; -template -class unique_lock { - using mutex_awaitable = std::invoke_result_t; struct awaitable { - unique_lock* m_lock; - mutex_awaitable m_awaitable; + basic_lock* m_owner; + mutex_awaitable_t m_impl; auto await_ready() noexcept { - return m_awaitable.await_ready(); + return m_impl.await_ready(); } template auto await_suspend(std::coroutine_handle enclosing) noexcept { - return m_awaitable.await_suspend(enclosing); + return m_impl.await_suspend(enclosing); } void await_resume() noexcept { - m_awaitable.await_resume(); - m_lock->m_owned = true; + m_impl.await_resume(); + m_owner->m_owned = true; } }; public: - unique_lock(Mutex& mtx, std::defer_lock_t) noexcept : m_mtx(&mtx), m_owned(false) {} - unique_lock(Mutex& mtx, std::adopt_lock_t) noexcept : m_mtx(&mtx), m_owned(true) {} - unique_lock(locked_mutex&& lk) noexcept : m_mtx(&lk.mutex()), m_owned(true) {} - unique_lock(unique_lock&& rhs) noexcept : m_mtx(rhs.m_mtx), m_owned(rhs.m_owned) { + basic_lock(Mutex& mtx, std::defer_lock_t) noexcept : m_mtx(&mtx), m_owned(false) {} + basic_lock(Mutex& mtx, std::adopt_lock_t) noexcept : m_mtx(&mtx), m_owned(true) {} + basic_lock(basic_locked_mutex&& lk) noexcept : m_mtx(&lk.mutex()), m_owned(true) {} + basic_lock(basic_lock&& rhs) noexcept : m_mtx(rhs.m_mtx), m_owned(rhs.m_owned) { rhs.m_mtx = nullptr; rhs.m_owned = false; } - unique_lock& operator=(unique_lock&& rhs) noexcept { + basic_lock& operator=(basic_lock&& rhs) noexcept { if (owns_lock()) { - m_mtx->unlock(); + (m_mtx->*Unlock)(); } m_mtx = std::exchange(rhs.m_mtx, nullptr); m_owned = std::exchange(rhs.m_owned, false); return *this; } - unique_lock(const unique_lock& rhs) = delete; - unique_lock& operator=(const unique_lock& rhs) = delete; - ~unique_lock() { + basic_lock(const basic_lock& rhs) = delete; + basic_lock& operator=(const basic_lock& rhs) = delete; + ~basic_lock() { if (owns_lock()) { - m_mtx->unlock(); + (m_mtx->*Unlock)(); } } bool try_lock() noexcept { assert(!owns_lock()); - m_owned = m_mtx->try_lock(); + m_owned = (m_mtx->*TryLock)(); return m_owned; } auto operator co_await() noexcept { assert(!owns_lock()); - return awaitable(this, m_mtx->exclusive()); + return awaitable{ this, (m_mtx->*Lock)() }; } void unlock() noexcept { assert(owns_lock()); - m_mtx->unlock(); + (m_mtx->*Unlock)(); m_owned = false; } @@ -128,92 +123,30 @@ class unique_lock { template -unique_lock(locked_mutex&& lk) -> unique_lock; - +class unique_lock : public basic_lock { + using basic_lock::basic_lock; +}; template -class shared_lock { - using mutex_awaitable = std::invoke_result_t; - struct awaitable { - shared_lock* m_lock; - mutex_awaitable m_awaitable; - - auto await_ready() noexcept { - return m_awaitable.await_ready(); - } - - template - auto await_suspend(std::coroutine_handle enclosing) noexcept { - return m_awaitable.await_suspend(enclosing); - } - - void await_resume() noexcept { - m_awaitable.await_resume(); - m_lock->m_owned = true; - } - }; - -public: - shared_lock(Mutex& mtx, std::defer_lock_t) noexcept : m_mtx(&mtx), m_owned(false) {} - shared_lock(Mutex& mtx, std::adopt_lock_t) noexcept : m_mtx(&mtx), m_owned(true) {} - shared_lock(locked_mutex_shared lk) noexcept : m_mtx(&lk.mutex()), m_owned(true) {} - shared_lock(shared_lock&& rhs) noexcept : m_mtx(rhs.m_mtx), m_owned(rhs.m_owned) { - rhs.m_mtx = nullptr; - rhs.m_owned = false; - } - shared_lock& operator=(shared_lock&& rhs) noexcept { - if (owns_lock()) { - m_mtx->unlock_shared(); - } - m_mtx = std::exchange(rhs.m_mtx, nullptr); - m_owned = std::exchange(rhs.m_owned, false); - return *this; - } - shared_lock(const shared_lock& rhs) = delete; - shared_lock& operator=(const shared_lock& rhs) = delete; - ~shared_lock() { - if (owns_lock()) { - m_mtx->unlock_shared(); - } - } - - bool try_lock() noexcept { - assert(!owns_lock()); - m_owned = m_mtx->try_lock_shared(); - return m_owned; - } - - auto operator co_await() noexcept { - assert(!owns_lock()); - return awaitable(this, m_mtx->shared()); - } - - void unlock() noexcept { - assert(owns_lock()); - m_mtx->unlock_shared(); - m_owned = false; - } - - Mutex& mutex() const noexcept { - return *m_mtx; - } +class shared_lock : public basic_lock { + using basic_lock::basic_lock; +}; - bool owns_lock() const noexcept { - return m_owned; - } - operator bool() const noexcept { - return owns_lock(); - } - -private: - Mutex* m_mtx; - bool m_owned = false; -}; +template +unique_lock(exclusively_locked_mutex) -> unique_lock; +template +unique_lock(Mutex&, std::adopt_lock_t) -> unique_lock; +template +unique_lock(Mutex&, std::defer_lock_t) -> unique_lock; template -shared_lock(locked_mutex_shared lk) -> shared_lock; +shared_lock(shared_locked_mutex) -> shared_lock; +template +shared_lock(Mutex&, std::adopt_lock_t) -> shared_lock; +template +shared_lock(Mutex&, std::defer_lock_t) -> shared_lock; } // namespace asyncpp \ No newline at end of file diff --git a/include/asyncpp/mutex.hpp b/include/asyncpp/mutex.hpp index 0cd77de..d45416c 100644 --- a/include/asyncpp/mutex.hpp +++ b/include/asyncpp/mutex.hpp @@ -22,7 +22,7 @@ class mutex { template Promise> bool await_suspend(std::coroutine_handle enclosing) noexcept; - locked_mutex await_resume() noexcept; + exclusively_locked_mutex await_resume() noexcept; }; bool add_awaiting(awaitable* waiting); diff --git a/include/asyncpp/shared_mutex.hpp b/include/asyncpp/shared_mutex.hpp index d0dc498..30c9a86 100644 --- a/include/asyncpp/shared_mutex.hpp +++ b/include/asyncpp/shared_mutex.hpp @@ -34,7 +34,7 @@ class shared_mutex { : basic_awaitable(owner, awaitable_type::exclusive) {} bool await_ready() const noexcept; - locked_mutex await_resume() const noexcept; + exclusively_locked_mutex await_resume() const noexcept; }; struct shared_awaitable : basic_awaitable { @@ -42,7 +42,7 @@ class shared_mutex { : basic_awaitable(owner, awaitable_type::shared) {} bool await_ready() const noexcept; - locked_mutex_shared await_resume() const noexcept; + shared_locked_mutex await_resume() const noexcept; }; bool add_awaiting(basic_awaitable* waiting); diff --git a/src/mutex.cpp b/src/mutex.cpp index 012841b..ced6874 100644 --- a/src/mutex.cpp +++ b/src/mutex.cpp @@ -11,7 +11,7 @@ bool mutex::awaitable::await_ready() const noexcept { } -locked_mutex mutex::awaitable::await_resume() noexcept { +exclusively_locked_mutex mutex::awaitable::await_resume() noexcept { assert(m_owner); return { m_owner }; } diff --git a/src/shared_mutex.cpp b/src/shared_mutex.cpp index 4386c13..3ba671e 100644 --- a/src/shared_mutex.cpp +++ b/src/shared_mutex.cpp @@ -17,13 +17,13 @@ bool shared_mutex::shared_awaitable::await_ready() const noexcept { } -locked_mutex shared_mutex::exclusive_awaitable::await_resume() const noexcept { +exclusively_locked_mutex shared_mutex::exclusive_awaitable::await_resume() const noexcept { assert(m_owner); return { m_owner }; } -locked_mutex_shared shared_mutex::shared_awaitable::await_resume() const noexcept { +shared_locked_mutex shared_mutex::shared_awaitable::await_resume() const noexcept { assert(m_owner); return { m_owner }; }