Created
July 16, 2017 09:24
-
-
Save ciniml/e85c08664ee307645321ec3ce3973cc6 to your computer and use it in GitHub Desktop.
C++11 std::future like class template for FreeRTOS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef FREERTOS_FUTURE_HPP__ | |
#define FREERTOS_FUTURE_HPP__ | |
#include <type_traits> | |
#include <utility> | |
#include "freertos/FreeRTOS.h" | |
#include "freertos/task.h" | |
#include "freertos/semphr.h" | |
#include "freertos/event_groups.h" | |
namespace freertos | |
{ | |
class Mutex | |
{ | |
private: | |
StaticSemaphore_t body; | |
SemaphoreHandle_t handle; | |
bool is_locked; | |
public: | |
Mutex() : handle(nullptr), is_locked(false) | |
{ | |
this->handle = xSemaphoreCreateMutexStatic(&this->body); | |
} | |
void lock() | |
{ | |
xSemaphoreTake(this->handle, portMAX_DELAY); | |
this->is_locked = true; | |
} | |
void release() | |
{ | |
this->is_locked = false; | |
xSemaphoreGive(this->handle); | |
} | |
~Mutex() | |
{ | |
if (this->handle != nullptr) { | |
if (this->is_locked) { | |
this->release(); | |
} | |
vSemaphoreDelete(this->handle); | |
this->handle = nullptr; | |
} | |
} | |
}; | |
class WaitEvent | |
{ | |
private: | |
typedef std::unique_ptr< std::remove_pointer<EventGroupHandle_t>::type, decltype(&vEventGroupDelete)> HandleType; | |
HandleType handle; | |
public: | |
WaitEvent() : handle(nullptr, vEventGroupDelete) | |
{ | |
this->handle.reset(xEventGroupCreate()); | |
} | |
WaitEvent(const WaitEvent&) = delete; | |
WaitEvent(WaitEvent&& source) : handle(std::move(source.handle)) {} | |
void clear() | |
{ | |
xEventGroupClearBits(this->handle.get(), 1); | |
} | |
void set() | |
{ | |
xEventGroupSetBits(this->handle.get(), 1); | |
} | |
void wait() | |
{ | |
xEventGroupWaitBits(this->handle.get(), 1, pdFALSE, pdTRUE, portMAX_DELAY); | |
} | |
bool is_valid() const { return this->handle.operator bool(); } | |
}; | |
template<typename TLock> | |
class LockGuard | |
{ | |
private: | |
TLock& lock; | |
public: | |
LockGuard(TLock* lock) : lock(*lock) | |
{ | |
this->lock.lock(); | |
} | |
LockGuard(TLock& lock) : lock(lock) | |
{ | |
this->lock.lock(); | |
} | |
~LockGuard() | |
{ | |
this->lock.release(); | |
} | |
}; | |
template<typename TResult> class future; | |
template<typename TResult> | |
class promise_base | |
{ | |
protected: | |
friend class future<TResult>; | |
struct SharedState | |
{ | |
struct Deleter | |
{ | |
void operator()(TResult* result) { result->~TResult(); } | |
}; | |
typename std::aligned_storage<sizeof(TResult)>::type storage; | |
std::unique_ptr<TResult, Deleter> result; | |
WaitEvent event; | |
Mutex mutex; | |
void set_value(const TResult& value) | |
{ | |
{ | |
LockGuard<Mutex>(this->mutex); | |
this->result.reset(new(&this->storage) TResult(value)); | |
} | |
this->event.set(); | |
} | |
void set_value(TResult&& value) noexcept | |
{ | |
{ | |
LockGuard<Mutex>(this->mutex); | |
this->result.reset(new(&this->storage) TResult(std::forward<TResult>(value))); | |
} | |
this->event.set(); | |
} | |
void wait() | |
{ | |
this->event.wait(); | |
} | |
TResult get_result() | |
{ | |
this->wait(); | |
return *this->result; | |
} | |
}; | |
std::shared_ptr<SharedState> state; | |
typedef promise_base<TResult> SelfType; | |
promise_base() : state(new SharedState()) {} | |
promise_base(const SelfType& other) = delete; | |
promise_base(SelfType&& source) noexcept : state(std::move(source)) {} | |
public: | |
void set_value(TResult&& result) | |
{ | |
this->state->set_value(std::forward<TResult>(result)); | |
} | |
void set_value(const TResult& result) | |
{ | |
this->state->set_value(result); | |
} | |
}; | |
template<typename TResult> class promise; | |
template<typename TResult> | |
class future | |
{ | |
friend class promise<TResult>; | |
private: | |
typedef promise_base<TResult> PromiseType; | |
typedef typename PromiseType::SharedState SharedState; | |
std::shared_ptr<SharedState> state; | |
future(const std::shared_ptr<SharedState>& state) : state(state) {} | |
public: | |
void wait() { | |
this->state->wait(); | |
} | |
TResult get() { | |
return this->state->get_result(); | |
} | |
}; | |
template<typename TResult> | |
class promise : public promise_base<TResult> | |
{ | |
public: | |
typedef future<TResult> FutureType; | |
private: | |
public: | |
FutureType get_future() | |
{ | |
return FutureType(this->state); | |
} | |
}; | |
}; | |
#endif //FREERTOS_FUTURE_HPP__ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment