mirror of
https://gitlab.com/niansa/cosched.git
synced 2025-03-06 20:53:26 +01:00
Implemented experimental async mutex
This commit is contained in:
parent
9d1047be54
commit
ecacf7f9f7
2 changed files with 68 additions and 0 deletions
|
@ -8,6 +8,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
add_library(cosched SHARED
|
add_library(cosched SHARED
|
||||||
scheduler.cpp include/scheduler.hpp
|
scheduler.cpp include/scheduler.hpp
|
||||||
scheduled_thread.cpp include/scheduled_thread.hpp
|
scheduled_thread.cpp include/scheduled_thread.hpp
|
||||||
|
include/scheduler_mutex.hpp
|
||||||
basic-coro/SingleEvent.cpp
|
basic-coro/SingleEvent.cpp
|
||||||
)
|
)
|
||||||
target_include_directories(cosched PUBLIC include/ basic-coro/include/)
|
target_include_directories(cosched PUBLIC include/ basic-coro/include/)
|
||||||
|
|
67
include/scheduler_mutex.hpp
Normal file
67
include/scheduler_mutex.hpp
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
#ifndef SCHEDULER_MUTEX_HPP
|
||||||
|
#define SCHEDULER_MUTEX_HPP
|
||||||
|
#include "scheduler.hpp"
|
||||||
|
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
|
|
||||||
|
namespace CoSched {
|
||||||
|
class Mutex {
|
||||||
|
bool held = false;
|
||||||
|
std::queue<Task*> resume_on_unlock;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Mutex() {}
|
||||||
|
Mutex(const Mutex&) = delete;
|
||||||
|
Mutex(Mutex&&) = delete;
|
||||||
|
~Mutex() {
|
||||||
|
unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
AwaitableTask<void> 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<void> lock() {
|
||||||
|
co_await mutex.lock();
|
||||||
|
held_by_us = true;
|
||||||
|
}
|
||||||
|
void unlock() {
|
||||||
|
mutex.unlock();
|
||||||
|
held_by_us = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif // SCHEDULER_MUTEX_HPP
|
Loading…
Add table
Reference in a new issue