/*+ ARES/HADES/BORG Package -- ./libLSS/tools/defer.hpp Copyright (C) 2018-2020 Guilhem Lavaux Copyright (C) 2009-2020 Jens Jasche Additional contributions from: Guilhem Lavaux (2023) +*/ #ifndef __LIBLSS_TOOLS_DEFER_HPP # define __LIBLSS_TOOLS_DEFER_HPP # include # include # include "libLSS/tools/console.hpp" namespace LibLSS { struct DeferTypes { enum State { WAIT, READY, ERROR }; typedef std::function Function; }; struct DeferState : DeferTypes { std::vector ready_f, error_f; State state; DeferState(State s) : state(s) {} }; /** * @brief Add Future like concept for ARES. * If some state is not guaranteed to exist at a given time, a Defer can be * added to a class. Other class may subscribe to this Defer to receive asynchronously * an information on the change of status of the Defer. */ class Defer : public DeferTypes { protected: std::shared_ptr state_p; public: /** * @brief Construct a new Defer object * */ Defer() : state_p(std::make_shared(WAIT)) {} /** * @brief Destroy the Defer object * */ ~Defer() {} /** * @brief Check whether the defer is still is waiting status. * * @return true if it is still waiting. * @return false if it is READY or FAIL. */ bool isWaiting() const { return state_p->state == WAIT; } /** * @brief Subscribe a new functor to be called when state is becoming ready. * * @param f Functor to be called */ void ready(Function f) { if (state_p->state == READY) { f(); return; } else if (state_p->state == WAIT) { state_p->ready_f.push_back(f); } } /** * @brief Subscribe a new functor to be called when state is becoming fail. * * @param f Functor to be called. */ void fail(Function f) { if (state_p->state == ERROR) { f(); return; } else if (state_p->state == WAIT) { state_p->error_f.push_back(f); } } /** * @brief Submit a state change to READY. * */ void submit_ready() { if (state_p->state == READY) return; Console::instance().c_assert( state_p->state == WAIT, "State has already changed (in submit_ready)."); state_p->state = READY; for (auto &f : state_p->ready_f) { f(); } state_p->ready_f.clear(); } /** * @brief Submit a state change to FAIL. * */ void submit_error() { if (state_p->state == ERROR) return; Console::instance().c_assert( state_p->state == WAIT, "State has already changed (in submit_error)."); state_p->state = ERROR; for (auto &f : state_p->error_f) { f(); } state_p->error_f.clear(); } }; template class PromisePointer { private: typedef std::shared_ptr Pointer_t; Pointer_t ptr; public: Defer defer; Pointer_t get() { return ptr; } PromisePointer(Pointer_t starter) : ptr(starter) {} }; template auto make_promise_pointer(std::shared_ptr p) { return PromisePointer(p); } } // namespace LibLSS #endif // ARES TAG: num_authors = 1 // ARES TAG: name(0) = Guilhem Lavaux // ARES TAG: email(0) = guilhem.lavaux@iap.fr // ARES TAG: year(0) = 2018-2020