diff --git a/kernel/include/kernel/Lock/RWLock.h b/kernel/include/kernel/Lock/RWLock.h new file mode 100644 index 00000000..f0b61271 --- /dev/null +++ b/kernel/include/kernel/Lock/RWLock.h @@ -0,0 +1,97 @@ +#pragma once + +#include +#include + +namespace Kernel +{ + + class RWLock + { + BAN_NON_COPYABLE(RWLock); + BAN_NON_MOVABLE(RWLock); + public: + RWLock() = default; + + void rd_lock() + { + LockGuard _(m_mutex); + while (m_writers_waiting > 0 || m_writer_active) + m_thread_blocker.block_indefinite(&m_mutex); + m_readers_active++; + } + + void rd_unlock() + { + LockGuard _(m_mutex); + if (--m_readers_active == 0) + m_thread_blocker.unblock(); + } + + void wr_lock() + { + LockGuard _(m_mutex); + m_writers_waiting++; + while (m_readers_active > 0 || m_writer_active) + m_thread_blocker.block_indefinite(&m_mutex); + m_writers_waiting--; + m_writer_active = true; + } + + + void wr_unlock() + { + LockGuard _(m_mutex); + m_writer_active = false; + m_thread_blocker.unblock(); + } + + private: + Mutex m_mutex; + ThreadBlocker m_thread_blocker; + uint32_t m_readers_active { 0 }; + uint32_t m_writers_waiting { 0 }; + bool m_writer_active { false }; + }; + + class RWLockRDGuard + { + BAN_NON_COPYABLE(RWLockRDGuard); + BAN_NON_MOVABLE(RWLockRDGuard); + public: + RWLockRDGuard(RWLock& lock) + : m_lock(lock) + { + m_lock.rd_lock(); + } + + ~RWLockRDGuard() + { + m_lock.rd_unlock(); + } + + private: + RWLock& m_lock; + }; + + class RWLockWRGuard + { + BAN_NON_COPYABLE(RWLockWRGuard); + BAN_NON_MOVABLE(RWLockWRGuard); + public: + RWLockWRGuard(RWLock& lock) + : m_lock(lock) + { + m_lock.wr_lock(); + } + + ~RWLockWRGuard() + { + m_lock.wr_unlock(); + } + + private: + RWLock& m_lock; + }; + +}