From ecacf7f9f750db0cc33dc05753c1ad9210d878e4 Mon Sep 17 00:00:00 2001 From: niansa Date: Mon, 22 May 2023 22:46:30 +0200 Subject: [PATCH] Implemented experimental async mutex --- CMakeLists.txt | 1 + include/scheduler_mutex.hpp | 67 +++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 include/scheduler_mutex.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 92d0772..e19f192 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,6 +8,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) add_library(cosched SHARED scheduler.cpp include/scheduler.hpp scheduled_thread.cpp include/scheduled_thread.hpp + include/scheduler_mutex.hpp basic-coro/SingleEvent.cpp ) target_include_directories(cosched PUBLIC include/ basic-coro/include/) diff --git a/include/scheduler_mutex.hpp b/include/scheduler_mutex.hpp new file mode 100644 index 0000000..ed995f5 --- /dev/null +++ b/include/scheduler_mutex.hpp @@ -0,0 +1,67 @@ +#ifndef SCHEDULER_MUTEX_HPP +#define SCHEDULER_MUTEX_HPP +#include "scheduler.hpp" + +#include + + +namespace CoSched { +class Mutex { + bool held = false; + std::queue resume_on_unlock; + +public: + Mutex() {} + Mutex(const Mutex&) = delete; + Mutex(Mutex&&) = delete; + ~Mutex() { + unlock(); + } + + AwaitableTask lock() { + // Just hold lock and return if lock isn't currently being held + if (!held) { + held = true; + co_return; + } + // Lock is already being held, add task to queue and suspend until lock is passed + auto& task = Task::get_current(); + resume_on_unlock.push(&task); + task.set_suspended(true); + co_await task.yield(); + } + void unlock() { + // If nothing is waiting for the lock to release, just release it and we're done + if (!resume_on_unlock.empty()) { + held = false; + return; + } + // Something is waiting or the lock to be released, just pass it by. + resume_on_unlock.front()->set_suspended(false); + } +}; + + +class ScopedLock { + Mutex& mutex; + bool held_by_us = false; + +public: + ScopedLock(Mutex &m) : mutex(m) {} + ScopedLock(const ScopedLock&) = delete; + ScopedLock(ScopedLock&&) = delete; + ~ScopedLock() { + if (held_by_us) unlock(); + } + + AwaitableTask lock() { + co_await mutex.lock(); + held_by_us = true; + } + void unlock() { + mutex.unlock(); + held_by_us = false; + } +}; +} +#endif // SCHEDULER_MUTEX_HPP