From 0e51c90b78469c7c2067935ef62bf9474d09891d Mon Sep 17 00:00:00 2001 From: Gabriel Corona Date: Wed, 18 May 2016 13:33:41 +0200 Subject: [PATCH] [s4u] Move the actor logic out of the Actor class --- examples/s4u/basic/s4u_basic.cpp | 25 +++------- examples/s4u/io/s4u_io.cpp | 12 ++--- include/simgrid/s4u/actor.hpp | 83 ++++++++++++-------------------- include/simgrid/s4u/comm.hpp | 12 ++--- src/s4u/s4u_actor.cpp | 71 +++++++++++++-------------- src/s4u/s4u_comm.cpp | 35 ++++++-------- 6 files changed, 99 insertions(+), 139 deletions(-) diff --git a/examples/s4u/basic/s4u_basic.cpp b/examples/s4u/basic/s4u_basic.cpp index 0a7c018ad0..bfe6c022f4 100644 --- a/examples/s4u/basic/s4u_basic.cpp +++ b/examples/s4u/basic/s4u_basic.cpp @@ -9,31 +9,23 @@ XBT_LOG_NEW_DEFAULT_CATEGORY(s4u_test, "a sample log category"); -class Worker : simgrid::s4u::Actor { +class Worker { public: - Worker(const char*procname, simgrid::s4u::Host *host,int argc, char **argv) - : simgrid::s4u::Actor(procname,host,argc,argv){} - - int main(int argc, char **argv) { + int operator()() { XBT_INFO("Hello s4u, I'm ready to serve"); - - char *msg = (char*)recv(*simgrid::s4u::Mailbox::byName("worker")); + char *msg = (char*)simgrid::s4u::Actor::recv(*simgrid::s4u::Mailbox::byName("worker")); XBT_INFO("I received '%s'",msg); XBT_INFO("I'm done. See you."); return 1; } }; -class Master : simgrid::s4u::Actor { +class Master { public: - Master(const char*procname, simgrid::s4u::Host *host,int argc, char **argv) - : Actor(procname,host,argc,argv){} - - int main(int argc, char **argv) { + int operator()() { const char *msg = "GaBuZoMeu"; XBT_INFO("Hello s4u, I have something to send"); - send(*simgrid::s4u::Mailbox::byName("worker"), xbt_strdup(msg), strlen(msg)); - + simgrid::s4u::Actor::send(*simgrid::s4u::Mailbox::byName("worker"), xbt_strdup(msg), strlen(msg)); XBT_INFO("I'm done. See you."); return 1; } @@ -43,9 +35,8 @@ public: int main(int argc, char **argv) { simgrid::s4u::Engine *e = new simgrid::s4u::Engine(&argc,argv); e->loadPlatform("../../platforms/two_hosts_platform.xml"); - - new Worker("worker", simgrid::s4u::Host::by_name("host0"), 0, NULL); - new Master("master", simgrid::s4u::Host::by_name("host1"), 0, NULL); + new simgrid::s4u::Actor("worker", simgrid::s4u::Host::by_name("host0"), Worker()); + new simgrid::s4u::Actor("master", simgrid::s4u::Host::by_name("host1"), 0, Master()); e->run(); return 0; } diff --git a/examples/s4u/io/s4u_io.cpp b/examples/s4u/io/s4u_io.cpp index 20a3db2975..922d56dc43 100644 --- a/examples/s4u/io/s4u_io.cpp +++ b/examples/s4u/io/s4u_io.cpp @@ -11,10 +11,8 @@ XBT_LOG_NEW_DEFAULT_CATEGORY(s4u_test, "a sample log category"); -class myHost : simgrid::s4u::Actor { +class MyHost { public: - myHost(const char*procname, simgrid::s4u::Host *host,int argc, char **argv) -: simgrid::s4u::Actor(procname,host,argc,argv){} void show_info(boost::unordered_map const&mounts) { XBT_INFO("Storage info on %s:", @@ -34,7 +32,7 @@ public: } } - int main(int argc, char **argv) { + int operator()() { boost::unordered_map const& mounts = simgrid::s4u::Host::current()->mountedStorages(); @@ -105,11 +103,11 @@ public: } }; -int main(int argc, char **argv) { +int main(int argc, char **argv) +{ simgrid::s4u::Engine *e = new simgrid::s4u::Engine(&argc,argv); e->loadPlatform("../../platforms/storage/storage.xml"); - - new myHost("host", simgrid::s4u::Host::by_name("denise"), 0, NULL); + new simgrid::s4u::Actor("host", simgrid::s4u::Host::by_name("denise"), MyHost()); e->run(); return 0; } diff --git a/include/simgrid/s4u/actor.hpp b/include/simgrid/s4u/actor.hpp index 24790755b2..a58eb6ccd3 100644 --- a/include/simgrid/s4u/actor.hpp +++ b/include/simgrid/s4u/actor.hpp @@ -27,34 +27,34 @@ namespace s4u { * * \verbatim * #include "s4u/actor.hpp" - * - * class Worker : simgrid::s4u::Actor { - * - * int main(int argc, char **argv) { - * printf("Hello s4u"); - * } + * + * class Worker { + * int operator()() { + * printf("Hello s4u"); + * return 0; + * } * }; + * + * new Actor("worker", host, Worker()); * \endverbatim * */ XBT_PUBLIC_CLASS Actor { - friend Comm; Actor(smx_process_t smx_proc); public: - Actor(const char*name, s4u::Host *host, int argc, char **argv); - Actor(const char*name, s4u::Host *host, int argc, char **argv, double killTime); - virtual ~Actor() {} + 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(); - /** The main method of your agent */ - virtual int main(int argc, char **argv); - - /** The Actor that is currently running */ - static Actor &self(); /** Retrieves the actor that have the given PID (or NULL if not existing) */ //static Actor *byPid(int pid); not implemented /** Retrieves the name of that actor */ - const char*getName(); + const char* getName(); /** Retrieves the host on which that actor is running */ s4u::Host *getHost(); /** Retrieves the PID of that actor */ @@ -67,8 +67,6 @@ public: /** Retrieves the time at which that actor will be killed (or -1 if not set) */ double getKillTime(); - /** Ask kindly to all actors to die. Only the issuer will survive. */ - static void killAll(); /** Ask the actor to die. * * It will only notice your request when doing a simcall next time (a communication or similar). @@ -76,64 +74,47 @@ public: */ void kill(); + // Static methods on all actors: + + /** Ask kindly to all actors to die. Only the issuer will survive. */ + static void killAll(); + + // Static methods working on the current actor: + /** Block the actor sleeping for that amount of seconds (may throws hostFailure) */ - void sleep(double duration); + static void sleep(double duration); /** Block the actor, computing the given amount of flops */ - e_smx_state_t execute(double flop); + static e_smx_state_t execute(double flop); /** Block the actor until it gets a message from the given mailbox. * * See \ref Comm for the full communication API (including non blocking communications). */ - void *recv(Mailbox &chan); + static void *recv(Mailbox &chan); /** Block the actor until it delivers a message of the given simulated size to the given mailbox * * See \ref Comm for the full communication API (including non blocking communications). */ - void send(Mailbox &chan, void*payload, size_t simulatedSize); + static void send(Mailbox &chan, void*payload, size_t simulatedSize); protected: smx_process_t getInferior() {return pimpl_;} private: - smx_process_t pimpl_; + smx_process_t pimpl_ = nullptr; }; + }} // namespace simgrid::s4u #endif /* SIMGRID_S4U_ACTOR_HPP */ #if 0 -public abstract class Actor implements Runnable { - /** Suspends the process. See {@link #resume()} to resume it afterward */ - public native void suspend(); - /** Resume a process that was suspended by {@link #suspend()}. */ - public native void resume(); - /** Tests if a process is suspended. */ - public native boolean isSuspended(); +public final class Actor { - /** - * Returns the value of a given process property. - */ - public native String getProperty(String name); - - - /** - * Migrates a process to another host. - * - * @param host The host where to migrate the process. - * - */ - public native void migrate(Host host); - - public native void exit(); - /** - * This static method returns the current amount of processes running - * - * @return The count of the running processes - */ - public native static int getCount(); + public Actor(String name, Host host, double killTime, Runnable code); + // .... } #endif diff --git a/include/simgrid/s4u/comm.hpp b/include/simgrid/s4u/comm.hpp index c9d615c8bf..be969c2a6d 100644 --- a/include/simgrid/s4u/comm.hpp +++ b/include/simgrid/s4u/comm.hpp @@ -26,13 +26,13 @@ public: public: /** Creates (but don't start) an async send to the mailbox #dest */ - static Comm &send_init(Actor *sender, Mailbox &dest); + static Comm &send_init(Mailbox &dest); /** Creates and start an async send to the mailbox #dest */ - static Comm &send_async(s4u::Actor *sender, Mailbox &dest, void *data, int simulatedByteAmount); + static Comm &send_async(Mailbox &dest, void *data, int simulatedByteAmount); /** Creates (but don't start) an async recv onto the mailbox #from */ - static Comm &recv_init(s4u::Actor *receiver, Mailbox &from); + static Comm &recv_init(Mailbox &from); /** Creates and start an async recv to the mailbox #from */ - static Comm &recv_async(s4u::Actor *receiver, Mailbox &from, void **data); + static Comm &recv_async(Mailbox &from, void **data); void start() override; void wait() override; @@ -72,8 +72,8 @@ private: /* FIXME: expose these elements in the API */ void (*copyDataFunction_)(smx_synchro_t, void*, size_t) = NULL; private: - Actor *sender_ = NULL; - Actor *receiver_ = NULL; + smx_process_t sender_ = NULL; + smx_process_t receiver_ = NULL; Mailbox *mailbox_ = NULL; }; diff --git a/src/s4u/s4u_actor.cpp b/src/s4u/s4u_actor.cpp index 04962097b5..40a9c30519 100644 --- a/src/s4u/s4u_actor.cpp +++ b/src/s4u/s4u_actor.cpp @@ -14,45 +14,34 @@ XBT_LOG_NEW_DEFAULT_CATEGORY(s4u_actor,"S4U actors"); -/* C main function of a actor, running this->main */ static int s4u_actor_runner(int argc, char **argv) { - simgrid::s4u::Actor *actor = (simgrid::s4u::Actor*) SIMIX_process_self_get_data(); - int res = actor->main(argc,argv); - return res; + // Move the callback from the heap to the stack: + std::unique_ptr> code2 = + std::unique_ptr>( + static_cast*>( + SIMIX_process_self_get_data())); + std::function code = std::move(*code2); + code2 = nullptr; + // Call it: + // TODO, handle exceptions + return code(); } - - using namespace simgrid; -s4u::Actor::Actor(smx_process_t smx_proc) { - pimpl_ = smx_proc; -} -s4u::Actor::Actor(const char *name, s4u::Host *host, int argc, char **argv) - : s4u::Actor::Actor(name,host, argc,argv, -1) { -} -s4u::Actor::Actor(const char *name, s4u::Host *host, int argc, char **argv, double killTime) { - pimpl_ = simcall_process_create(name, s4u_actor_runner, this, host->name().c_str(), killTime, argc, argv, NULL/*properties*/,0); - - xbt_assert(pimpl_,"Cannot create the actor"); -// TRACE_msg_process_create(procname, simcall_process_get_PID(p_smx_process), host->getInferior()); -// simcall_process_on_exit(p_smx_process,(int_f_pvoid_pvoid_t)TRACE_msg_process_kill,p_smx_process); -} +s4u::Actor::Actor(smx_process_t smx_proc) : pimpl_(smx_proc) {} -int s4u::Actor::main(int argc, char **argv) { - fprintf(stderr,"Error: You should override the method main(int, char**) in Actor class %s\n",getName()); - return 0; -} -s4u::Actor &s4u::Actor::self() +s4u::Actor::Actor(const char* name, s4u::Host *host, double killTime, std::function code) { - smx_process_t smx_proc = SIMIX_process_self(); - simgrid::s4u::Actor* res = (simgrid::s4u::Actor*) SIMIX_process_self_get_data(); - if (res == NULL) // The smx_process was not created by S4U (but by deployment?). Embed it in a S4U object - res = new Actor(smx_proc); - return *res; + std::function* code2 = new std::function(std::move(code)); + this->pimpl_ = simcall_process_create( + name, s4u_actor_runner, code2, host->name().c_str(), + killTime, 0, NULL, NULL, 0); } +s4u::Actor::~Actor() {} + void s4u::Actor::setAutoRestart(bool autorestart) { simcall_process_auto_restart_set(pimpl_,autorestart); } @@ -60,9 +49,11 @@ void s4u::Actor::setAutoRestart(bool autorestart) { s4u::Host *s4u::Actor::getHost() { return s4u::Host::by_name(sg_host_get_name(simcall_process_get_host(pimpl_))); } + const char* s4u::Actor::getName() { return simcall_process_get_name(pimpl_); } + int s4u::Actor::getPid(){ return simcall_process_get_PID(pimpl_); } @@ -70,16 +61,21 @@ int s4u::Actor::getPid(){ void s4u::Actor::setKillTime(double time) { simcall_process_set_kill_time(pimpl_,time); } + double s4u::Actor::getKillTime() { return simcall_process_get_kill_time(pimpl_); } -void s4u::Actor::killAll() { - simcall_process_killall(1); -} + void s4u::Actor::kill() { simcall_process_kill(pimpl_); } +// static stuff: + +void s4u::Actor::killAll() { + simcall_process_killall(1); +} + void s4u::Actor::sleep(double duration) { simcall_process_sleep(duration); } @@ -90,16 +86,15 @@ e_smx_state_t s4u::Actor::execute(double flops) { } void *s4u::Actor::recv(Mailbox &chan) { - void *res=NULL; - - Comm c = Comm::recv_init(this, chan); + void *res = NULL; + Comm c = Comm::recv_init(chan); c.setDstData(&res,sizeof(res)); c.wait(); - - return res; + return res; } + void s4u::Actor::send(Mailbox &chan, void *payload, size_t simulatedSize) { - Comm c = Comm::send_init(this,chan); + Comm c = Comm::send_init(chan); c.setRemains(simulatedSize); c.setSrcData(payload); // c.start() is optional. diff --git a/src/s4u/s4u_comm.cpp b/src/s4u/s4u_comm.cpp index fb272f4961..93e1c506dc 100644 --- a/src/s4u/s4u_comm.cpp +++ b/src/s4u/s4u_comm.cpp @@ -16,18 +16,17 @@ s4u::Comm::~Comm() { } -s4u::Comm &s4u::Comm::send_init(s4u::Actor *sender, s4u::Mailbox &chan) { +s4u::Comm &s4u::Comm::send_init(s4u::Mailbox &chan) { s4u::Comm *res = new s4u::Comm(); - res->sender_ = sender; + res->sender_ = SIMIX_process_self(); res->mailbox_ = &chan; - return *res; } -s4u::Comm &s4u::Comm::recv_init(s4u::Actor *receiver, s4u::Mailbox &chan) { + +s4u::Comm &s4u::Comm::recv_init(s4u::Mailbox &chan) { s4u::Comm *res = new s4u::Comm(); - res->receiver_ = receiver; + res->receiver_ = SIMIX_process_self(); res->mailbox_ = &chan; - return *res; } @@ -73,12 +72,12 @@ void s4u::Comm::start() { xbt_assert(state_ == inited); if (srcBuff_ != NULL) { // Sender side - pimpl_ = simcall_comm_isend(sender_->getInferior(), mailbox_->getInferior(), remains_, rate_, + pimpl_ = simcall_comm_isend(sender_, mailbox_->getInferior(), remains_, rate_, srcBuff_, srcBuffSize_, matchFunction_, cleanFunction_, copyDataFunction_, userData_, detached_); } else if (dstBuff_ != NULL) { // Receiver side - pimpl_ = simcall_comm_irecv(receiver_->getInferior(), mailbox_->getInferior(), dstBuff_, &dstBuffSize_, + pimpl_ = simcall_comm_irecv(receiver_, mailbox_->getInferior(), dstBuff_, &dstBuffSize_, matchFunction_, copyDataFunction_, userData_, rate_); @@ -94,12 +93,12 @@ void s4u::Comm::wait() { simcall_comm_wait(pimpl_, -1/*timeout*/); else {// p_state == inited. Save a simcall and do directly a blocking send/recv if (srcBuff_ != NULL) { - simcall_comm_send(sender_->getInferior(), mailbox_->getInferior(), remains_, rate_, + simcall_comm_send(sender_, mailbox_->getInferior(), remains_, rate_, srcBuff_, srcBuffSize_, matchFunction_, copyDataFunction_, userData_, -1 /*timeout*/); } else { - simcall_comm_recv(receiver_->getInferior(), mailbox_->getInferior(), dstBuff_, &dstBuffSize_, + simcall_comm_recv(receiver_, mailbox_->getInferior(), dstBuff_, &dstBuffSize_, matchFunction_, copyDataFunction_, userData_, -1/*timeout*/, rate_); } @@ -117,34 +116,30 @@ void s4u::Comm::wait(double timeout) { // It's not started yet. Do it in one simcall if (srcBuff_ != NULL) { - simcall_comm_send(sender_->getInferior(), mailbox_->getInferior(), remains_, rate_, + simcall_comm_send(sender_, mailbox_->getInferior(), remains_, rate_, srcBuff_, srcBuffSize_, matchFunction_, copyDataFunction_, userData_, timeout); } else { // Receiver - simcall_comm_recv(receiver_->getInferior(), mailbox_->getInferior(), dstBuff_, &dstBuffSize_, + simcall_comm_recv(receiver_, mailbox_->getInferior(), dstBuff_, &dstBuffSize_, matchFunction_, copyDataFunction_, userData_, timeout, rate_); } state_ = finished; } -s4u::Comm &s4u::Comm::send_async(s4u::Actor *sender, Mailbox &dest, void *data, int simulatedSize) { - s4u::Comm &res = s4u::Comm::send_init(sender, dest); - +s4u::Comm &s4u::Comm::send_async(Mailbox &dest, void *data, int simulatedSize) { + s4u::Comm &res = s4u::Comm::send_init(dest); res.setRemains(simulatedSize); res.srcBuff_ = data; res.srcBuffSize_ = sizeof(void*); - res.start(); return res; } -s4u::Comm &s4u::Comm::recv_async(s4u::Actor *receiver, Mailbox &dest, void **data) { - s4u::Comm &res = s4u::Comm::recv_init(receiver, dest); - +s4u::Comm &s4u::Comm::recv_async(Mailbox &dest, void **data) { + s4u::Comm &res = s4u::Comm::recv_init(dest); res.setDstData(data); - res.start(); return res; } -- 2.20.1