Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[s4u] More support for C++-style time and durations
[simgrid.git] / include / simgrid / s4u / actor.hpp
index 52c7286..5039f84 100644 (file)
@@ -7,14 +7,21 @@
 #define SIMGRID_S4U_ACTOR_HPP
 
 #include <atomic>
+#include <chrono>
 #include <functional>
 #include <memory>
 #include <stdexcept>
+#include <string>
 #include <type_traits>
+#include <utility>
+#include <vector>
+
+#include <boost/intrusive_ptr.hpp>
 
 #include <xbt/base.h>
 #include <xbt/functional.hpp>
 
+#include <simgrid/chrono.hpp>
 #include <simgrid/simix.h>
 #include <simgrid/s4u/forward.hpp>
 
@@ -123,7 +130,10 @@ namespace s4u {
 
 /** @brief Simulation Agent (see \ref s4u_actor)*/
 XBT_PUBLIC_CLASS Actor {
-private:
+  friend Mailbox;
+  friend simgrid::simix::Process;
+  smx_process_t pimpl_ = nullptr;
+
   /** Wrap a (possibly non-copyable) single-use task into a `std::function` */
   template<class F, class... Args>
   static std::function<void()> wrap_task(F f, Args... args)
@@ -135,40 +145,42 @@ private:
       (*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>;
+
+  // ***** 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<void()> code);
+  static Ptr createActor(const char* name, s4u::Host *host, double killTime, std::function<void()> code);
 
-  Actor(const char* name, s4u::Host *host, std::function<void()> code)
-    : Actor(name, host, -1.0, std::move(code)) {};
+  static Ptr createActor(const char* name, s4u::Host *host, std::function<void()> code)
+  {
+    return createActor(name, host, -1.0, std::move(code));
+  }
 
   /** Create an actor using code
    *
@@ -181,18 +193,23 @@ public:
     // This constructor is enabled only if the call code(args...) is valid:
     typename = typename std::result_of<F(Args...)>::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:
 
-  Actor(const char* name, s4u::Host *host, double killTime,
+  static Ptr createActor(const char* name, s4u::Host *host, double killTime,
     const char* function, std::vector<std::string> args);
 
-  Actor(const char* name, s4u::Host *host, const char* function,
+  static Ptr createActor(const char* name, s4u::Host *host, const char* function,
       std::vector<std::string> args)
-    : Actor(name, host, -1.0, function, std::move(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
@@ -219,7 +236,7 @@ public:
   void kill();
 
   static void kill(int pid);
-  static Actor forPid(int pid);
+  static Ptr forPid(int pid);
   
   /**
    * Wait for the actor to finish.
@@ -230,13 +247,12 @@ public:
 
   /** Ask kindly to all actors to die. Only the issuer will survive. */
   static void killAll();
-
-  bool valid() const { return pimpl_ != nullptr; }
-
-private:
-  smx_process_t pimpl_ = nullptr;
+  
+  smx_process_t getInferior();
 };
 
+using ActorPtr = Actor::Ptr;
+
 /** @ingroup s4u_api
  *  @brief Static methods working on the current actor (see @ref s4u::Actor) */
 namespace this_actor {
@@ -244,6 +260,13 @@ namespace this_actor {
   /** Block the actor sleeping for that amount of seconds (may throws hostFailure) */
   XBT_PUBLIC(void) sleep(double duration);
 
+  template<class Rep, class Period>
+  inline void sleep(std::chrono::duration<Rep, Period> duration)
+  {
+    auto seconds = std::chrono::duration_cast<SimulationClockDuration>(duration);
+    sleep(seconds.count());
+  }
+
   /** Block the actor, computing the given amount of flops */
   XBT_PUBLIC(e_smx_state_t) execute(double flop);