1
0
Fork 0
mirror of https://gitlab.com/niansa/cosched.git synced 2025-03-06 20:53:26 +01:00
cosched/include/scheduler_mutex.hpp
2023-05-22 22:46:30 +02:00

67 lines
1.5 KiB
C++

#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