/* * 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" #include "threads_signal.hpp" namespace Threads { template class ExclusiveSignal : public Signallable , public Awaitable> { 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 await() override { return await(PrimitiveThread::getCurrentThread()); } result_type await(const long timeout) override { return await(PrimitiveThread::getCurrentThread(), timeout); } #endif result_type await(const PrimitiveThread& currentThread) override { return await(currentThread, portMAX_DELAY); } result_type await(const PrimitiveThread& currentThread, const long timeout) override { waiting_thread_ = currentThread; const bool notified = currentThread.notifyWait(timeout); if (!notified) { return std::nullopt; } else { return current_value_; } } bool emit(const value_type& v) override { current_value_ = v; if (!waiting_thread_) { return false; } else { return waiting_thread_->notify(0, eNoAction); } } std::pair emitFromIsr(const value_type& v) override { current_value_ = v; if (!waiting_thread_) { return {false, pdFALSE}; } else { auto const [discard, was_notified] = waiting_thread_->notifyFromIsr(0, eNoAction); (void) discard; return {true, was_notified}; } } private: result_type current_value_; std::optional waiting_thread_; }; template<> struct ExclusiveSignal : public Signallable , public Awaitable { 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 await() override { return await(PrimitiveThread::getCurrentThread()); } result_type await(const long timeout) override { return await(PrimitiveThread::getCurrentThread(), timeout); } #endif result_type await(const PrimitiveThread& currentThread) override { return await(currentThread, portMAX_DELAY); } result_type await(const PrimitiveThread& currentThread, const long timeout) override { waiting_thread_ = currentThread; return currentThread.notifyWait(timeout); } void emit() override { if (waiting_thread_) { auto const _ = waiting_thread_->notify(0, eNoAction); (void) _; } } BaseType_t emitFromIsr() override { if (!waiting_thread_) { return pdFALSE; } else { auto const [discard, was_notified] = waiting_thread_->notifyFromIsr(0, eNoAction); (void) discard; return was_notified; } } private: std::optional waiting_thread_; }; }// namespace Threads #endif /* SKULLC_THREADS_EXCLUSIVESIGNAL_HPP_ */