diff --git a/source/mijin/async/task_mutex.hpp b/source/mijin/async/task_mutex.hpp new file mode 100644 index 0000000..ce2a9c3 --- /dev/null +++ b/source/mijin/async/task_mutex.hpp @@ -0,0 +1,63 @@ + +#pragma once + +#ifndef MIJIN_ASYNC_TASK_MUTEX_HPP_INCLUDED +#define MIJIN_ASYNC_TASK_MUTEX_HPP_INCLUDED 1 + +#include "./coroutine.hpp" + +namespace mijin +{ +class [[nodiscard]] TaskMutexLock +{ +private: + class TaskMutex* mutex_; + +public: + explicit TaskMutexLock(class TaskMutex* mutex) noexcept : mutex_(mutex) {} + TaskMutexLock(const TaskMutexLock&) = delete; + TaskMutexLock(TaskMutexLock&& other) noexcept : mutex_(std::exchange(other.mutex_, nullptr)) {} + + TaskMutexLock& operator=(const TaskMutexLock&) = delete; + inline TaskMutexLock& operator=(TaskMutexLock&& other) noexcept; + inline ~TaskMutexLock() noexcept; +}; + +class TaskMutex +{ +private: + bool locked_ = false; +public: + Task c_lock() + { + while (locked_) + { + co_await c_suspend(); + } + locked_ = true; + co_return TaskMutexLock(this); + } + + friend class TaskMutexLock; +}; + +TaskMutexLock::~TaskMutexLock() noexcept +{ + if (mutex_) + { + mutex_->locked_ = false; + } +} + +TaskMutexLock& TaskMutexLock::operator=(TaskMutexLock&& other) noexcept +{ + if (mutex_) + { + mutex_->locked_ = false; + } + mutex_ = std::exchange(other.mutex_, nullptr); + return *this; +} +} + +#endif // MIJIN_ASYNC_TASK_MUTEX_HPP_INCLUDED \ No newline at end of file