X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/7b138f8b1ed3e8816eda5cb26deb71fe81b4087a..cabfcca7cb25b7aa54d7ee1b0a8b117940b85a8d:/include/simgrid/s4u/actor.hpp diff --git a/include/simgrid/s4u/actor.hpp b/include/simgrid/s4u/actor.hpp index 89a752e4cf..28dbdc4031 100644 --- a/include/simgrid/s4u/actor.hpp +++ b/include/simgrid/s4u/actor.hpp @@ -7,15 +7,21 @@ #define SIMGRID_S4U_ACTOR_HPP #include +#include #include -#include #include #include +#include #include +#include +#include + +#include #include #include +#include #include #include @@ -124,70 +130,57 @@ 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_; - }; + friend Mailbox; + friend simgrid::simix::Process; + smx_process_t pimpl_ = nullptr; + /** 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)...)); + typedef decltype(f(std::move(args)...)) R; + auto task = std::make_shared>( + simgrid::xbt::makeTask(std::move(f), std::move(args)...)); return [=] { (*task)(); }; } + + Actor(smx_process_t pimpl) : pimpl_(pimpl) {} + public: - Actor() : pimpl_(nullptr) {} - Actor(smx_process_t smx_proc) : - pimpl_(SIMIX_process_ref(smx_proc)) {} - ~Actor() - { - SIMIX_process_unref(pimpl_); - } - // Copy+move (with the copy-and-swap idiom): - Actor(Actor const& actor) : pimpl_(SIMIX_process_ref(actor.pimpl_)) {} - friend void swap(Actor& first, Actor& second) - { - using std::swap; - swap(first.pimpl_, second.pimpl_); - } - Actor& operator=(Actor actor) + // ***** No copy ***** + + Actor(Actor const&) = delete; + Actor& operator=(Actor const&) = delete; + + // ***** Reference count (delegated to pimpl_) ***** + + friend void intrusive_ptr_add_ref(Actor* actor) { - swap(*this, actor); - return *this; + xbt_assert(actor != nullptr); + SIMIX_process_ref(actor->pimpl_); } - Actor(Actor&& actor) : pimpl_(nullptr) + friend void intrusive_ptr_release(Actor* actor) { - swap(*this, actor); + xbt_assert(actor != nullptr); + SIMIX_process_unref(actor->pimpl_); } + using Ptr = boost::intrusive_ptr; + + // ***** Actor creation ***** /** 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); + static Ptr createActor(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.0d, std::move(code)) {}; + static Ptr createActor(const char* name, s4u::Host *host, std::function code) + { + return createActor(name, host, -1.0, std::move(code)); + } /** Create an actor using code * @@ -200,9 +193,23 @@ public: // This constructor is enabled only if the call code(args...) is valid: typename = typename std::result_of::type > - Actor(const char* name, s4u::Host *host, F code, Args... args) : - Actor(name, host, wrap_task(std::move(code), std::move(args)...)) - {} + static Ptr createActor(const char* name, s4u::Host *host, F code, Args... args) + { + return createActor(name, host, wrap_task(std::move(code), std::move(args)...)); + } + + // Create actor from function name: + + static Ptr createActor(const char* name, s4u::Host *host, double killTime, + const char* function, std::vector args); + + static Ptr createActor(const char* name, s4u::Host *host, const char* function, + std::vector args) + { + return createActor(name, host, -1.0, function, std::move(args)); + } + + // ***** Methods ***** /** Retrieves the actor that have the given PID (or NULL if not existing) */ //static Actor *byPid(int pid); not implemented @@ -229,6 +236,7 @@ public: void kill(); static void kill(int pid); + static Ptr forPid(int pid); /** * Wait for the actor to finish. @@ -240,16 +248,38 @@ public: /** Ask kindly to all actors to die. Only the issuer will survive. */ static void killAll(); -private: - smx_process_t pimpl_ = nullptr; + /** Returns the internal implementation of this actor */ + smx_process_t getImpl(); }; +using ActorPtr = Actor::Ptr; + /** @ingroup s4u_api * @brief Static methods working on the current actor (see @ref s4u::Actor) */ namespace this_actor { /** Block the actor sleeping for that amount of seconds (may throws hostFailure) */ - XBT_PUBLIC(void) sleep(double duration); + XBT_PUBLIC(void) sleep_for(double duration); + XBT_PUBLIC(void) sleep_until(double timeout); + + template + inline void sleep_for(std::chrono::duration duration) + { + auto seconds = std::chrono::duration_cast(duration); + this_actor::sleep_for(seconds.count()); + } + template + inline void sleep_until(const SimulationTimePoint& timeout_time) + { + auto timeout_native = std::chrono::time_point_cast(timeout_time); + this_actor::sleep_until(timeout_native.time_since_epoch().count()); + } + + XBT_ATTRIB_DEPRECATED("Use sleep_for()") + inline void sleep(double duration) + { + return sleep_for(duration); + } /** Block the actor, computing the given amount of flops */ XBT_PUBLIC(e_smx_state_t) execute(double flop); @@ -265,6 +295,11 @@ namespace this_actor { * See \ref Comm for the full communication API (including non blocking communications). */ XBT_PUBLIC(void) send(Mailbox &chan, void*payload, size_t simulatedSize); + + /** + * Return the PID of the current actor. + */ + XBT_PUBLIC(int) getPid(); };