int main(int argc, char **argv) {
simgrid::s4u::Engine *e = new simgrid::s4u::Engine(&argc,argv);
e->loadPlatform("../../platforms/two_hosts.xml");
- simgrid::s4u::Actor("worker", simgrid::s4u::Host::by_name("Tremblay"), Worker());
- simgrid::s4u::Actor("master", simgrid::s4u::Host::by_name("Jupiter"), Master());
+ simgrid::s4u::Actor::createActor("worker", simgrid::s4u::Host::by_name("Tremblay"), Worker());
+ simgrid::s4u::Actor::createActor("master", simgrid::s4u::Host::by_name("Jupiter"), Master());
e->run();
return 0;
}
e->registerFunction<Worker>("worker");
e->registerFunction<Master>("master");
std::vector<std::string> args;
- simgrid::s4u::Actor("worker", simgrid::s4u::Host::by_name("Tremblay"), "worker", args);
- simgrid::s4u::Actor("master", simgrid::s4u::Host::by_name("Jupiter"), "master", args);
+ simgrid::s4u::Actor::createActor("worker", simgrid::s4u::Host::by_name("Tremblay"), "worker", args);
+ simgrid::s4u::Actor::createActor("master", simgrid::s4u::Host::by_name("Jupiter"), "master", args);
e->run();
return 0;
}
{
simgrid::s4u::Engine *e = new simgrid::s4u::Engine(&argc,argv);
e->loadPlatform("../../platforms/storage/storage.xml");
- simgrid::s4u::Actor("host", simgrid::s4u::Host::by_name("denise"), MyHost());
+ simgrid::s4u::Actor::createActor("host", simgrid::s4u::Host::by_name("denise"), MyHost());
e->run();
return 0;
}
for (int i = 0; i < NB_ACTOR * 2 ; i++) {
// To create a worker use the static method simgrid::s4u::Actor.
if((i % 2) == 0 )
- simgrid::s4u::Actor("worker", simgrid::s4u::Host::by_name("Jupiter"), workerLockGuard, mutex, std::ref(result));
+ simgrid::s4u::Actor::createActor("worker", simgrid::s4u::Host::by_name("Jupiter"), workerLockGuard, mutex, std::ref(result));
else
- simgrid::s4u::Actor("worker", simgrid::s4u::Host::by_name("Tremblay"), worker, mutex, std::ref(result));
+ simgrid::s4u::Actor::createActor("worker", simgrid::s4u::Host::by_name("Tremblay"), worker, mutex, std::ref(result));
}
simgrid::s4u::this_actor::sleep(10);
{
simgrid::s4u::Engine *e = new simgrid::s4u::Engine(&argc,argv);
e->loadPlatform("../../platforms/two_hosts.xml");
- simgrid::s4u::Actor("main", simgrid::s4u::Host::by_name("Tremblay"), master);
+ simgrid::s4u::Actor::createActor("main", simgrid::s4u::Host::by_name("Tremblay"), master);
e->run();
return 0;
}
#include <utility>
#include <vector>
+#include <boost/intrusive_ptr.hpp>
+
#include <xbt/base.h>
#include <xbt/functional.hpp>
/** @brief Simulation Agent (see \ref s4u_actor)*/
XBT_PUBLIC_CLASS Actor {
friend Mailbox;
+ friend simgrid::simix::Process;
+ smx_process_t pimpl_ = nullptr;
-private:
/** 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)
(*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
*
// 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
void kill();
static void kill(int pid);
- static Actor forPid(int pid);
+ static Ptr forPid(int pid);
/**
* Wait for the actor to finish.
/** Ask kindly to all actors to die. Only the issuer will survive. */
static void killAll();
-
- bool valid() const { return pimpl_ != nullptr; }
smx_process_t getInferior();
-private:
- smx_process_t pimpl_ = nullptr;
};
+using ActorPtr = Actor::Ptr;
+
/** @ingroup s4u_api
* @brief Static methods working on the current actor (see @ref s4u::Actor) */
namespace this_actor {
* It means that the communications sent to this mailbox will start flowing to its host even before he does a recv().
* This models the real behavior of TCP and MPI communications, amongst other.
*/
- void setReceiver(Actor process);
+ void setReceiver(Actor* process);
/** Return the process declared as permanent receiver, or nullptr if none **/
- Actor receiver();
+ Actor& receiver();
private:
std::string name_;
namespace simgrid {
namespace s4u {
-Actor::Actor(const char* name, s4u::Host *host, double killTime, std::function<void()> code)
+// ***** Actor creation *****
+
+ActorPtr Actor::createActor(const char* name, s4u::Host *host, double killTime, std::function<void()> code)
{
// TODO, when autorestart is used, the std::function is copied so the new
// instance will get a fresh (reinitialized) state. Is this what we want?
- this->pimpl_ = SIMIX_process_ref(simcall_process_create(
+ smx_process_t process = simcall_process_create(
name, std::move(code), nullptr, host->name().c_str(),
- killTime, nullptr, 0));
+ killTime, nullptr, 0);
+ return Ptr(&process->actor());
}
-Actor::Actor(const char* name, s4u::Host *host, double killTime,
+ActorPtr Actor::createActor(const char* name, s4u::Host *host, double killTime,
const char* function, std::vector<std::string> args)
{
simgrid::simix::ActorCodeFactory& factory = SIMIX_get_actor_code_factory(function);
simgrid::simix::ActorCode code = factory(std::move(args));
- this->pimpl_ = SIMIX_process_ref(simcall_process_create(
+ smx_process_t process = simcall_process_create(
name, std::move(code), nullptr, host->name().c_str(),
- killTime, nullptr, 0));
+ killTime, nullptr, 0);
+ return ActorPtr(&process->actor());
}
+// ***** Actor methods *****
+
void Actor::join() {
simcall_process_join(pimpl_, -1);
}
return pimpl_;
}
-
void Actor::kill() {
simcall_process_kill(pimpl_);
}
-simgrid::s4u::Actor Actor::forPid(int pid)
+// ***** Static functions *****
+
+ActorPtr Actor::forPid(int pid)
{
- // Should we throw if we did not find it?
smx_process_t process = SIMIX_process_from_PID(pid);
- return simgrid::s4u::Actor(process);
+ if (process != nullptr)
+ return ActorPtr(&process->actor());
+ else
+ return nullptr;
}
-// static stuff:
-
void Actor::killAll() {
simcall_process_killall(1);
}
+// ***** this_actor *****
+
namespace this_actor {
void sleep(double duration) {
#include "xbt/log.h"
#include "src/msg/msg_private.h"
#include "src/simix/smx_network_private.h"
+#include "src/simix/smx_process_private.h"
#include "simgrid/s4u/mailbox.hpp"
return nullptr == simcall_mbox_front(pimpl_);
}
-void Mailbox::setReceiver(Actor actor) {
- simcall_mbox_set_receiver(pimpl_, actor.pimpl_);
+void Mailbox::setReceiver(Actor* actor) {
+ simcall_mbox_set_receiver(pimpl_, actor == nullptr ? nullptr : actor->pimpl_);
}
+
/** @brief get the receiver (process associated to the mailbox) */
-Actor Mailbox::receiver() {
- return Actor(pimpl_->permanent_receiver.get());
+Actor& Mailbox::receiver() {
+ return pimpl_->permanent_receiver->actor();
}
}
return mbox->empty();
}
void sg_mbox_setReceiver(sg_mbox_t mbox, smx_process_t process) {
- mbox->setReceiver(process);
+ mbox->setReceiver(&process->actor());
}
smx_process_t sg_mbox_receiver(sg_mbox_t mbox) {
return mbox->receiver().getInferior();
#include <xbt/string.hpp>
#include <simgrid/simix.hpp>
+#include <simgrid/s4u/actor.hpp>
+
#include "simgrid/simix.h"
#include "popping_private.h"
class Process {
public:
+ Process() : actor_(this) {}
// TODO, replace with boost intrusive container hooks
s_xbt_swag_hookup_t process_hookup = { nullptr, nullptr }; /* simix_global->process_list */
~Process();
+ simgrid::s4u::Actor& actor() { return actor_; }
+
private:
std::atomic_int_fast32_t refcount_ { 1 };
+ simgrid::s4u::Actor actor_;
};
}