From 4ab9ce4a821e477f097f19e94a0239299fbe25ea Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Sun, 26 Jul 2026 20:03:39 +0200 Subject: kstd: split mutex header --- libs/kstd/CMakeLists.txt | 2 +- libs/kstd/kstd/bits/concepts.hpp | 9 ++- libs/kstd/kstd/bits/mutex/lock_guard.hpp | 42 ++++++++++++++ libs/kstd/kstd/bits/mutex/mutex.cpp | 36 ++++++++++++ libs/kstd/kstd/bits/mutex/mutex.hpp | 45 +++++++++++++++ libs/kstd/kstd/bits/mutex/tags.hpp | 25 ++++++++ libs/kstd/kstd/mutex.cpp | 36 ------------ libs/kstd/kstd/mutex.hpp | 99 +------------------------------- 8 files changed, 160 insertions(+), 134 deletions(-) create mode 100644 libs/kstd/kstd/bits/mutex/lock_guard.hpp create mode 100644 libs/kstd/kstd/bits/mutex/mutex.cpp create mode 100644 libs/kstd/kstd/bits/mutex/mutex.hpp create mode 100644 libs/kstd/kstd/bits/mutex/tags.hpp delete mode 100644 libs/kstd/kstd/mutex.cpp (limited to 'libs') diff --git a/libs/kstd/CMakeLists.txt b/libs/kstd/CMakeLists.txt index e2b56d2f..63428c4b 100644 --- a/libs/kstd/CMakeLists.txt +++ b/libs/kstd/CMakeLists.txt @@ -17,8 +17,8 @@ add_library("kstd::lib" ALIAS "kstd") target_sources("kstd" PRIVATE "kstd/os/error.cpp" - "kstd/mutex.cpp" "kstd/system_error.cpp" + "kstd/bits/mutex/mutex.cpp" "kstd/bits/format/vformat.cpp" ) diff --git a/libs/kstd/kstd/bits/concepts.hpp b/libs/kstd/kstd/bits/concepts.hpp index 74c25cb1..f43f4f55 100644 --- a/libs/kstd/kstd/bits/concepts.hpp +++ b/libs/kstd/kstd/bits/concepts.hpp @@ -3,6 +3,7 @@ #include #include + namespace kstd::bits { @@ -10,6 +11,12 @@ namespace kstd::bits concept container_compatible_range = std::ranges::input_range && std::convertible_to, ValueType>; -} + template + concept basic_lockable = requires(LockableType & lockable) { + lockable.lock(); + lockable.unlock(); + }; + +} // namespace kstd::bits #endif diff --git a/libs/kstd/kstd/bits/mutex/lock_guard.hpp b/libs/kstd/kstd/bits/mutex/lock_guard.hpp new file mode 100644 index 00000000..b4762c36 --- /dev/null +++ b/libs/kstd/kstd/bits/mutex/lock_guard.hpp @@ -0,0 +1,42 @@ +#ifndef KSTD_BITS_MUTEX_LOCK_GUARD +#define KSTD_BITS_MUTEX_LOCK_GUARD + +// IWYU pragma: private, include + +#include +#include + +namespace kstd +{ + + //! An RAII wrapper for lockable objects. + template + struct lock_guard + { + using mutex_type = LockableType; + + //! Wrap a lockable and lock it. + explicit lock_guard(mutex_type & lockable) noexcept + : m_lockable{lockable} + { + m_lockable.lock(); + } + + lock_guard(mutex_type & lockable, adopt_lock_t) noexcept + : m_lockable{lockable} + {} + + lock_guard(lock_guard const &) = delete; + + ~lock_guard() + { + m_lockable.unlock(); + } + + private: + LockableType & m_lockable; + }; + +} // namespace kstd + +#endif \ No newline at end of file diff --git a/libs/kstd/kstd/bits/mutex/mutex.cpp b/libs/kstd/kstd/bits/mutex/mutex.cpp new file mode 100644 index 00000000..f1f43141 --- /dev/null +++ b/libs/kstd/kstd/bits/mutex/mutex.cpp @@ -0,0 +1,36 @@ +#include + +#include + +#include + +namespace kstd +{ + + mutex::mutex() = default; + + mutex::~mutex() + { + if (m_locked.test(std::memory_order_relaxed)) + { + os::panic("[KSTD] Tried to destroy a locked mutex."); + } + } + + auto mutex::lock() -> void + { + while (!try_lock()) + ; + } + + auto mutex::try_lock() -> bool + { + return !m_locked.test_and_set(std::memory_order_acquire); + } + + auto mutex::unlock() -> void + { + m_locked.clear(std::memory_order_release); + } + +} // namespace kstd diff --git a/libs/kstd/kstd/bits/mutex/mutex.hpp b/libs/kstd/kstd/bits/mutex/mutex.hpp new file mode 100644 index 00000000..baf00718 --- /dev/null +++ b/libs/kstd/kstd/bits/mutex/mutex.hpp @@ -0,0 +1,45 @@ +#ifndef KSTD_BITS_MUTEX_MUTEX_HPP +#define KSTD_BITS_MUTEX_MUTEX_HPP + +// IWYU pragma: private, include + +#include + +namespace kstd +{ + + //! A non-recursive mutex. + struct mutex + { + mutex(); + ~mutex(); + + mutex(mutex const &) = delete; + mutex(mutex &&) = delete; + + auto operator=(mutex const &) -> mutex & = delete; + auto operator=(mutex &&) -> mutex & = delete; + + //! Lock the mutex. + //! + //! @note This function blocks for as long as the mutex is not available. + auto lock() -> void; + + //! Try to lock the mutex. + //! + //! @note This function never blocks. + //! @return @p true iff. the mutex was successfully locked, @p false otherwise. + auto try_lock() -> bool; + + //! Unlock the mutex. + //! + //! @note The behavior is undefined if the mutex is not currently held by the thread unlocking it. + auto unlock() -> void; + + private: + std::atomic_flag m_locked{}; + }; + +} // namespace kstd + +#endif \ No newline at end of file diff --git a/libs/kstd/kstd/bits/mutex/tags.hpp b/libs/kstd/kstd/bits/mutex/tags.hpp new file mode 100644 index 00000000..fe43f931 --- /dev/null +++ b/libs/kstd/kstd/bits/mutex/tags.hpp @@ -0,0 +1,25 @@ +#ifndef KSTD_BITS_MUTEX_TAGS_HPP +#define KSTD_BITS_MUTEX_TAGS_HPP + +// IWYU pragma: private, include + +#include + +namespace kstd +{ + + struct adopt_lock_t + { + } constexpr inline adopt_lock{}; + + struct defer_lock_t + { + } constexpr inline defer_lock{}; + + struct try_to_lock_t + { + } constexpr inline try_to_lock{}; + +} // namespace kstd + +#endif \ No newline at end of file diff --git a/libs/kstd/kstd/mutex.cpp b/libs/kstd/kstd/mutex.cpp deleted file mode 100644 index fbddf964..00000000 --- a/libs/kstd/kstd/mutex.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include - -#include - -#include - -namespace kstd -{ - - mutex::mutex() = default; - - mutex::~mutex() - { - if (m_locked.test(std::memory_order_relaxed)) - { - os::panic("[KSTD] Tried to destroy a locked mutex."); - } - } - - auto mutex::lock() -> void - { - while (!try_lock()) - ; - } - - auto mutex::try_lock() -> bool - { - return !m_locked.test_and_set(std::memory_order_acquire); - } - - auto mutex::unlock() -> void - { - m_locked.clear(std::memory_order_release); - } - -} // namespace kstd diff --git a/libs/kstd/kstd/mutex.hpp b/libs/kstd/kstd/mutex.hpp index b2a31aa9..6d482b6d 100644 --- a/libs/kstd/kstd/mutex.hpp +++ b/libs/kstd/kstd/mutex.hpp @@ -1,101 +1,8 @@ #ifndef KSTD_MUTEX_HPP #define KSTD_MUTEX_HPP -#include - -namespace kstd -{ - - //! A non-recursive mutex. - struct mutex - { - mutex(); - ~mutex(); - - mutex(mutex const &) = delete; - mutex(mutex &&) = delete; - - auto operator=(mutex const &) -> mutex & = delete; - auto operator=(mutex &&) -> mutex & = delete; - - //! Lock the mutex. - //! - //! @note This function blocks for as long as the mutex is not available. - auto lock() -> void; - - //! Try to lock the mutex. - //! - //! @note This function never blocks. - //! @return @p true iff. the mutex was successfully locked, @p false otherwise. - auto try_lock() -> bool; - - //! Unlock the mutex. - //! - //! @note The behavior is undefined if the mutex is not currently held by the thread unlocking it. - auto unlock() -> void; - - private: - std::atomic_flag m_locked{}; - }; - - //! A tag type to specify that a given @p lockable wrapper should adopt ownership of the @p lockable. - struct adopt_lock_t - { - explicit adopt_lock_t() = default; - } constexpr inline adopt_lock{}; - - //! A tag type to specify that a given @p lockable wrapper should defer locking the @p lockable. - struct defer_lock_t - { - explicit defer_lock_t() = default; - } constexpr inline defer_lock{}; - - //! A tag type to specify that a given @p lockable wrapper should attempt to lock the @p lockable. - struct try_to_lock_t - { - explicit try_to_lock_t() = default; - } constexpr inline try_to_lock{}; - - //! An RAII wrapper for a single @p lockable like a kstd::mutex. - template - struct lock_guard - { - using mutex_type = MutexType; - - //! Construct a new lock_guard and immediately lock the given mutex. - //! - //! @note This function will block until the mutex was successfully locked. - //! @param mutex The mutex to lock. - lock_guard(MutexType & mutex) noexcept - : m_mutex(mutex) - { - m_mutex.lock(); - } - - //! Construct a new lock_guard and take ownership of the given mutex. - //! - //! @note The behavior is undefined if the mutex is not owned by the current thread. - //! @param mutex The mutex to take ownership of. - lock_guard(MutexType & mutex, adopt_lock_t) noexcept - : m_mutex(mutex) - {} - - //! Destroy this lock_guard and release the owned mutex. - ~lock_guard() - { - m_mutex.unlock(); - } - - lock_guard(lock_guard const &) noexcept = delete; - lock_guard(lock_guard &&) noexcept = delete; - - auto operator=(lock_guard const &) noexcept -> lock_guard & = delete; - auto operator=(lock_guard &&) noexcept -> lock_guard & = delete; - - private: - mutex_type & m_mutex; - }; - -} // namespace kstd +#include // IWYU pragma: export +#include // IWYU pragma: export +#include // IWYU pragma: export #endif \ No newline at end of file -- cgit v1.2.3