/* * threads_signal.hpp * * Created on: Jun 11, 2021 * Author: erki */ #ifndef SKULLC_THREADS_EXCLUSIVESIGNAL_HPP_ #define SKULLC_THREADS_EXCLUSIVESIGNAL_HPP_ #include #include #include #include #include "threads_primitivethread.hpp" namespace Threads { template class ExclusiveSignal { public: using value_type = T; using result_type = std::optional; static_assert( std::is_trivially_copyable_v, "Signal's value must be trivially copyable."); ExclusiveSignal() : current_value_(std::nullopt) , waiting_thread_(std::nullopt) { } ExclusiveSignal(const ExclusiveSignal&) = delete; ExclusiveSignal(ExclusiveSignal&&) = delete; ExclusiveSignal& operator=(const ExclusiveSignal&) = delete; ExclusiveSignal& operator=(ExclusiveSignal&&) = delete; #ifdef INCLUDE_xTaskGetCurrentTaskHandle result_type wait() { return wait(PrimitiveThread::getCurrentThread()); } result_type wait(const long timeout) { return wait(PrimitiveThread::getCurrentThread(), timeout); } #endif result_type wait(const PrimitiveThread& currentThread) { return wait(currentThread, portMAX_DELAY); } result_type wait(const PrimitiveThread& currentThread, const long timeout) { waiting_thread_ = currentThread; const bool notified = currentThread.notifyWait(timeout); if (!notified) { return std::nullopt; } else { return current_value_; } } bool emit(const result_type& v) { current_value_ = v; if (!waiting_thread_) { return false; } else { return waiting_thread_->notify(0, eNoAction); } } private: result_type current_value_; std::optional waiting_thread_; }; template<> struct ExclusiveSignal { using value_type = void; using result_type = bool; ExclusiveSignal() : waiting_thread_(std::nullopt) { } ExclusiveSignal(const ExclusiveSignal&) = delete; ExclusiveSignal(ExclusiveSignal&&) = delete; ExclusiveSignal& operator=(const ExclusiveSignal&) = delete; ExclusiveSignal& operator=(ExclusiveSignal&&) = delete; #ifdef INCLUDE_xTaskGetCurrentTaskHandle result_type wait() { return wait(PrimitiveThread::getCurrentThread()); } result_type wait(const long timeout) { return wait(PrimitiveThread::getCurrentThread(), timeout); } #endif result_type wait(PrimitiveThread currentThread) { return wait(currentThread, portMAX_DELAY); } result_type wait(PrimitiveThread currentThread, const long timeout) { waiting_thread_ = currentThread; return currentThread.notifyWait(timeout); } bool emit() { if (!waiting_thread_) { return false; } else { return waiting_thread_->notify(0, eNoAction); } } private: std::optional waiting_thread_; }; } #endif /* SKULLC_THREADS_EXCLUSIVESIGNAL_HPP_ */