X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/83699b2ceb210166fbe71b73cc666413dd1df36b..7b138f8b1ed3e8816eda5cb26deb71fe81b4087a:/include/simgrid/s4u/actor.hpp diff --git a/include/simgrid/s4u/actor.hpp b/include/simgrid/s4u/actor.hpp index 092d14b42b..89a752e4cf 100644 --- a/include/simgrid/s4u/actor.hpp +++ b/include/simgrid/s4u/actor.hpp @@ -6,8 +6,16 @@ #ifndef SIMGRID_S4U_ACTOR_HPP #define SIMGRID_S4U_ACTOR_HPP +#include +#include +#include +#include #include +#include + #include +#include + #include #include @@ -113,9 +121,39 @@ namespace s4u { * * @{ */ - + /** @brief Simulation Agent (see \ref s4u_actor)*/ XBT_PUBLIC_CLASS Actor { +private: + /** Wrap a (possibly non-copyable) single-use task into a `std::function` */ + template + class Task { + public: + Task(F&& code, Args&&... args) : + code_(std::forward(code)), + args_(std::forward(args)...) + {} + void operator()() + { + if (done_.test_and_set()) + throw std::logic_error("Actor task already executed"); + simgrid::xbt::apply(std::move(code_), std::move(args_)); + } + private: + std::atomic_flag done_ = ATOMIC_FLAG_INIT; + F code_; + std::tuple args_; + }; + /** Wrap a (possibly non-copyable) single-use task into a `std::function` */ + template + static std::function wrap_task(F f, Args... args) + { + std::shared_ptr> task( + new Task(std::move(f), std::move(args)...)); + return [=] { + (*task)(); + }; + } public: Actor() : pimpl_(nullptr) {} Actor(smx_process_t smx_proc) : @@ -142,12 +180,29 @@ public: swap(*this, actor); } + /** Create an actor using a function + * + * If the actor is restarted, the actor has a fresh copy of the function. + */ Actor(const char* name, s4u::Host *host, double killTime, std::function code); + Actor(const char* name, s4u::Host *host, std::function code) - : Actor(name, host, -1, std::move(code)) {}; - template - Actor(const char* name, s4u::Host *host, C code) - : Actor(name, host, -1, std::function(std::move(code))) {} + : Actor(name, host, -1.0d, std::move(code)) {}; + + /** Create an actor using code + * + * Using this constructor, move-only type can be used. The consequence is + * that we cannot copy the value and restart the process in its initial + * state. In order to use auto-restart, an explicit `function` must be passed + * instead. + */ + template::type + > + Actor(const char* name, s4u::Host *host, F code, Args... args) : + Actor(name, host, wrap_task(std::move(code), std::move(args)...)) + {} /** Retrieves the actor that have the given PID (or NULL if not existing) */ //static Actor *byPid(int pid); not implemented