From: Gabriel Corona Date: Mon, 7 Dec 2015 15:58:50 +0000 (+0100) Subject: [simix] Encapsulate main function, argc and argv in a closure X-Git-Tag: v3_13~1474 X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/commitdiff_plain/be6e8d3215d3e25f48c7d2d0b359cf178f978d41?ds=sidebyside [simix] Encapsulate main function, argc and argv in a closure --- diff --git a/include/simgrid/simix.hpp b/include/simgrid/simix.hpp index 99f476f3d9..3002a4bd58 100644 --- a/include/simgrid/simix.hpp +++ b/include/simgrid/simix.hpp @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -26,10 +27,8 @@ public: ContextFactory(std::string name) : name_(std::move(name)) {} virtual ~ContextFactory(); - virtual Context* create_context( - xbt_main_func_t, int, char **, void_pfn_smxprocess_t, - smx_process_t process - ) = 0; + virtual Context* create_context(std::function code, + void_pfn_smxprocess_t cleanup, smx_process_t process) = 0; virtual void run_all() = 0; virtual Context* self(); std::string const& name() const @@ -49,23 +48,23 @@ protected: }; class Context { -protected: - xbt_main_func_t code_ = nullptr; - int argc_ = 0; - char **argv_ = nullptr; private: + std::function code_; void_pfn_smxprocess_t cleanup_func_ = nullptr; smx_process_t process_ = nullptr; public: bool iwannadie; public: - Context(xbt_main_func_t code, - int argc, char **argv, + Context(std::function code, void_pfn_smxprocess_t cleanup_func, smx_process_t process); - int operator()() + void operator()() + { + code_(); + } + bool has_code() const { - return code_(argc_, argv_); + return (bool) code_; } smx_process_t process() { diff --git a/src/bindings/java/JavaContext.cpp b/src/bindings/java/JavaContext.cpp index 12ebf6a42a..51ae35bcf9 100644 --- a/src/bindings/java/JavaContext.cpp +++ b/src/bindings/java/JavaContext.cpp @@ -41,10 +41,10 @@ JavaContext* JavaContextFactory::self() } JavaContext* JavaContextFactory::create_context( - xbt_main_func_t code, int argc, char ** argv, + std::function code, void_pfn_smxprocess_t cleanup, smx_process_t process) { - return this->new_context(code, argc, argv, cleanup, process); + return this->new_context(std::move(code), cleanup, process); } void JavaContextFactory::run_all() @@ -58,18 +58,17 @@ void JavaContextFactory::run_all() } -JavaContext::JavaContext(xbt_main_func_t code, - int argc, char **argv, +JavaContext::JavaContext(std::function code, void_pfn_smxprocess_t cleanup_func, smx_process_t process) - : Context(code, argc, argv, cleanup_func, process) + : Context(std::move(code), cleanup_func, process) { static int thread_amount=0; thread_amount++; /* If the user provided a function for the process then use it otherwise is the context for maestro */ - if (code) { + if (has_code()) { this->jprocess = nullptr; this->begin = xbt_os_sem_init(0); this->end = xbt_os_sem_init(0); diff --git a/src/bindings/java/JavaContext.hpp b/src/bindings/java/JavaContext.hpp index d773ad5d19..564938803b 100644 --- a/src/bindings/java/JavaContext.hpp +++ b/src/bindings/java/JavaContext.hpp @@ -37,8 +37,7 @@ public: xbt_os_sem_t end = nullptr; public: friend class JavaContextFactory; - JavaContext(xbt_main_func_t code, - int argc, char **argv, + JavaContext(std::function code, void_pfn_smxprocess_t cleanup_func, smx_process_t process); ~JavaContext() override; @@ -54,10 +53,8 @@ public: JavaContextFactory(); ~JavaContextFactory() override; JavaContext* self() override; - JavaContext* create_context( - xbt_main_func_t, int, char **, void_pfn_smxprocess_t, - smx_process_t process - ) override; + JavaContext* create_context(std::function code, + void_pfn_smxprocess_t, smx_process_t process) override; void run_all() override; }; diff --git a/src/msg/msg_process.c b/src/msg/msg_process.c index 12c1edd8cb..dd02f54009 100644 --- a/src/msg/msg_process.c +++ b/src/msg/msg_process.c @@ -82,7 +82,7 @@ msg_process_t MSG_process_create(const char *name, xbt_main_func_t code, void *data, msg_host_t host) { - return MSG_process_create_with_environment(name, code, data, host, -1, + return MSG_process_create_with_environment(name, code, data, host, 0, NULL, NULL); } diff --git a/src/simix/BoostContext.cpp b/src/simix/BoostContext.cpp index f2e5ceeeda..aa35075887 100644 --- a/src/simix/BoostContext.cpp +++ b/src/simix/BoostContext.cpp @@ -25,11 +25,10 @@ namespace simix { class BoostSerialContext : public BoostContext { public: - BoostSerialContext(xbt_main_func_t code, - int argc, char **argv, + BoostSerialContext(std::function code, void_pfn_smxprocess_t cleanup_func, smx_process_t process) - : BoostContext(code, argc, argv, cleanup_func, process) {} + : BoostContext(std::move(code), cleanup_func, process) {} void stop() override; void suspend() override; void resume(); @@ -38,11 +37,10 @@ public: #ifdef CONTEXT_THREADS class BoostParallelContext : public BoostContext { public: - BoostParallelContext(xbt_main_func_t code, - int argc, char **argv, + BoostParallelContext(std::function code, void_pfn_smxprocess_t cleanup_func, smx_process_t process) - : BoostContext(code, argc, argv, cleanup_func, process) {} + : BoostContext(std::move(code), cleanup_func, process) {} void stop() override; void suspend() override; void resume(); @@ -88,21 +86,20 @@ BoostContextFactory::~BoostContextFactory() #endif } -smx_context_t BoostContextFactory::create_context( - xbt_main_func_t code, int argc, char ** argv, +smx_context_t BoostContextFactory::create_context(std::function code, void_pfn_smxprocess_t cleanup_func, smx_process_t process) { BoostContext* context = nullptr; if (BoostContext::parallel_) #ifdef CONTEXT_THREADS context = this->new_context( - code, argc, argv, cleanup_func, process); + std::move(code), cleanup_func, process); #else xbt_die("No support for parallel execution"); #endif else context = this->new_context( - code, argc, argv, cleanup_func, process); + std::move(code), cleanup_func, process); return context; } @@ -139,16 +136,14 @@ static void smx_ctx_boost_wrapper(std::intptr_t arg) context->stop(); } -BoostContext::BoostContext(xbt_main_func_t code, - int argc, char **argv, - void_pfn_smxprocess_t cleanup_func, - smx_process_t process) - : Context(code, argc, argv, cleanup_func, process) +BoostContext::BoostContext(std::function code, + void_pfn_smxprocess_t cleanup_func, smx_process_t process) + : Context(std::move(code), cleanup_func, process) { /* if the user provided a function for the process then use it, otherwise it is the context for maestro */ - if (code) { + if (has_code()) { this->stack_ = SIMIX_context_stack_new(); // We need to pass the bottom of the stack to make_fcontext, // depending on the stack direction it may be the lower or higher address: diff --git a/src/simix/BoostContext.hpp b/src/simix/BoostContext.hpp index 4f64f4152d..d558d74c7b 100644 --- a/src/simix/BoostContext.hpp +++ b/src/simix/BoostContext.hpp @@ -43,8 +43,7 @@ protected: void* stack_ = nullptr; public: friend BoostContextFactory; - BoostContext(xbt_main_func_t code, - int argc, char **argv, + BoostContext(std::function code, void_pfn_smxprocess_t cleanup_func, smx_process_t process); ~BoostContext(); @@ -61,10 +60,8 @@ public: BoostContextFactory(); virtual ~BoostContextFactory(); - virtual Context* create_context( - xbt_main_func_t, int, char **, void_pfn_smxprocess_t, - smx_process_t process - ) override; + virtual Context* create_context(std::function code, + void_pfn_smxprocess_t, smx_process_t process) override; void run_all() override; }; diff --git a/src/simix/Context.cpp b/src/simix/Context.cpp index fbfffc9688..e6eec95bd7 100644 --- a/src/simix/Context.cpp +++ b/src/simix/Context.cpp @@ -4,6 +4,11 @@ /* This program is free software; you can redistribute it and/or modify it * under the terms of the license (GNU LGPL) which comes with this package. */ +#include +#include +#include +#include + #include #include "mc/mc.h" @@ -19,6 +24,88 @@ void SIMIX_process_set_cleanup_function( namespace simgrid { namespace simix { +class XBT_PRIVATE args { +private: + int argc_; + char** argv_; +public: + + // Main constructors + args() : argc_(0), argv_(nullptr) {} + args(int argc, char** argv) : argc_(argc), argv_(argv) {} + + // Free + void clear() + { + for (int i = 0; i < this->argc_; i++) + free(this->argv_[i]); + free(this->argv_); + this->argc_ = 0; + this->argv_ = nullptr; + } + ~args() { clear(); } + + // Copy + args(args const& that) = delete; + args& operator=(args const& that) = delete; + + // Move: + args(args&& that) : argc_(that.argc_), argv_(that.argv_) + { + that.argc_ = 0; + that.argv_ = nullptr; + } + args& operator=(args&& that) + { + this->argc_ = that.argc_; + this->argv_ = that.argv_; + that.argc_ = 0; + that.argv_ = nullptr; + return *this; + } + + int argc() const { return argc_; } + char** argv() { return argv_; } + const char*const* argv() const { return argv_; } + char* operator[](std::size_t i) { return argv_[i]; } +}; + +} +} + +static +std::function wrap_main(xbt_main_func_t code, int argc, char **argv) +{ + if (code) { + auto arg = std::make_shared(argc, argv); + return [=]() { + code(arg->argc(), arg->argv()); + }; + } else return std::function(); +} + +/** + * \brief creates a new context for a user level process + * \param code a main function + * \param argc the number of arguments of the main function + * \param argv the vector of arguments of the main function + * \param cleanup_func the function to call when the context stops + * \param cleanup_arg the argument of the cleanup_func function + */ +smx_context_t SIMIX_context_new( + xbt_main_func_t code, int argc, char **argv, + void_pfn_smxprocess_t cleanup_func, + smx_process_t simix_process) +{ + if (!simix_global) + xbt_die("simix is not initialized, please call MSG_init first"); + return simix_global->context_factory->create_context( + wrap_main(code, argc, argv), cleanup_func, simix_process); +} + +namespace simgrid { +namespace simix { + ContextFactoryInitializer factory_initializer = nullptr; ContextFactory::~ContextFactory() {} @@ -37,32 +124,21 @@ void ContextFactory::declare_context(void* context, std::size_t size) #endif } -Context::Context(xbt_main_func_t code, - int argc, char **argv, - void_pfn_smxprocess_t cleanup_func, - smx_process_t process) - : process_(process), iwannadie(false) +Context::Context(std::function code, + void_pfn_smxprocess_t cleanup_func, smx_process_t process) + : code_(std::move(code)), process_(process), iwannadie(false) { /* If the user provided a function for the process then use it. Otherwise, it is the context for maestro and we should set it as the current context */ - if (code) { + if (has_code()) this->cleanup_func_ = cleanup_func; - this->argc_ = argc; - this->argv_ = argv; - this->code_ = code; - } else { + else SIMIX_context_set_current(this); - } } Context::~Context() { - if (this->argv_) { - for (int i = 0; i < this->argc_; i++) - free(this->argv_[i]); - free(this->argv_); - } } void Context::stop() diff --git a/src/simix/RawContext.cpp b/src/simix/RawContext.cpp index 62474794c9..8aefa7177e 100644 --- a/src/simix/RawContext.cpp +++ b/src/simix/RawContext.cpp @@ -38,8 +38,7 @@ protected: void* stack_top_ = nullptr; public: friend class RawContextFactory; - RawContext(xbt_main_func_t code, - int argc, char **argv, + RawContext(std::function code, void_pfn_smxprocess_t cleanup_func, smx_process_t process); ~RawContext(); @@ -59,10 +58,8 @@ class RawContextFactory : public ContextFactory { public: RawContextFactory(); ~RawContextFactory(); - RawContext* create_context( - xbt_main_func_t, int, char **, void_pfn_smxprocess_t, - smx_process_t process - ) override; + RawContext* create_context(std::function code, + void_pfn_smxprocess_t, smx_process_t process) override; void run_all() override; private: void run_all_adaptative(); @@ -311,12 +308,10 @@ RawContextFactory::~RawContextFactory() #endif } -RawContext* RawContextFactory::create_context( - xbt_main_func_t code, int argc, char ** argv, - void_pfn_smxprocess_t cleanup, - smx_process_t process) +RawContext* RawContextFactory::create_context(std::function code, + void_pfn_smxprocess_t cleanup, smx_process_t process) { - return this->new_context(code, argc, argv, + return this->new_context(std::move(code), cleanup, process); } @@ -327,13 +322,11 @@ void RawContext::wrapper(void* arg) context->stop(); } -RawContext::RawContext( - xbt_main_func_t code, int argc, char ** argv, - void_pfn_smxprocess_t cleanup, - smx_process_t process) - : Context(code, argc, argv, cleanup, process) +RawContext::RawContext(std::function code, + void_pfn_smxprocess_t cleanup, smx_process_t process) + : Context(std::move(code), cleanup, process) { - if (code) { + if (has_code()) { this->stack_ = SIMIX_context_stack_new(); this->stack_top_ = raw_makecontext(this->stack_, smx_context_usable_stack_size, diff --git a/src/simix/ThreadContext.cpp b/src/simix/ThreadContext.cpp index 19be3d43cd..de4e718feb 100644 --- a/src/simix/ThreadContext.cpp +++ b/src/simix/ThreadContext.cpp @@ -45,22 +45,19 @@ ThreadContextFactory::~ThreadContextFactory() } ThreadContext* ThreadContextFactory::create_context( - xbt_main_func_t code, int argc, char ** argv, - void_pfn_smxprocess_t cleanup, - smx_process_t process) + std::function code, + void_pfn_smxprocess_t cleanup, smx_process_t process) { - return this->new_context(code, argc, argv, cleanup, process); + return this->new_context(std::move(code), cleanup, process); } -ThreadContext::ThreadContext(xbt_main_func_t code, - int argc, char **argv, - void_pfn_smxprocess_t cleanup, - smx_process_t process) - : Context(code, argc, argv, cleanup, process) +ThreadContext::ThreadContext(std::function code, + void_pfn_smxprocess_t cleanup, smx_process_t process) + : Context(std::move(code), cleanup, process) { /* If the user provided a function for the process then use it otherwise is the context for maestro */ - if (code) { + if (has_code()) { this->begin_ = xbt_os_sem_init(0); this->end_ = xbt_os_sem_init(0); if (smx_context_stack_size_was_set) diff --git a/src/simix/ThreadContext.hpp b/src/simix/ThreadContext.hpp index 4ecd959a5e..f0655b1161 100644 --- a/src/simix/ThreadContext.hpp +++ b/src/simix/ThreadContext.hpp @@ -21,8 +21,7 @@ class ThreadContextFactory; class ThreadContext : public Context { public: friend ThreadContextFactory; - ThreadContext(xbt_main_func_t code, - int argc, char **argv, + ThreadContext(std::function code, void_pfn_smxprocess_t cleanup_func, smx_process_t process); ~ThreadContext(); @@ -43,10 +42,8 @@ class ThreadContextFactory : public ContextFactory { public: ThreadContextFactory(); ~ThreadContextFactory(); - virtual ThreadContext* create_context( - xbt_main_func_t, int, char **, void_pfn_smxprocess_t, - smx_process_t process - ) override; + virtual ThreadContext* create_context(std::function code, + void_pfn_smxprocess_t cleanup_func, smx_process_t process) override; void run_all() override; ThreadContext* self() override; }; diff --git a/src/simix/UContext.cpp b/src/simix/UContext.cpp index a5e8e8f564..d2ce507b57 100644 --- a/src/simix/UContext.cpp +++ b/src/simix/UContext.cpp @@ -83,10 +83,8 @@ protected: char *stack_ = nullptr; /* the thread stack */ public: friend UContextFactory; - UContext(xbt_main_func_t code, - int argc, char **argv, - void_pfn_smxprocess_t cleanup_func, - smx_process_t process); + UContext(std::function code, + void_pfn_smxprocess_t cleanup_func, smx_process_t process); ~UContext(); protected: static void wrapper(int first, ...); @@ -94,11 +92,9 @@ protected: class SerialUContext : public UContext { public: - SerialUContext(xbt_main_func_t code, - int argc, char **argv, - void_pfn_smxprocess_t cleanup_func, - smx_process_t process) - : UContext(code, argc, argv, cleanup_func, process) + SerialUContext(std::function code, + void_pfn_smxprocess_t cleanup_func, smx_process_t process) + : UContext(std::move(code), cleanup_func, process) {} void stop() override; void suspend() override; @@ -107,11 +103,9 @@ public: class ParallelUContext : public UContext { public: - ParallelUContext(xbt_main_func_t code, - int argc, char **argv, - void_pfn_smxprocess_t cleanup_func, - smx_process_t process) - : UContext(code, argc, argv, cleanup_func, process) + ParallelUContext(std::function code, + void_pfn_smxprocess_t cleanup_func, smx_process_t process) + : UContext(std::move(code), cleanup_func, process) {} void stop() override; void suspend() override; @@ -126,10 +120,8 @@ public: UContextFactory(); virtual ~UContextFactory(); - virtual Context* create_context( - xbt_main_func_t, int, char **, void_pfn_smxprocess_t, - smx_process_t process - ) override; + virtual Context* create_context(std::function code, + void_pfn_smxprocess_t, smx_process_t process) override; void run_all() override; }; @@ -207,27 +199,22 @@ void UContextFactory::run_all() } } -Context* UContextFactory::create_context( - xbt_main_func_t code, int argc, char ** argv, - void_pfn_smxprocess_t cleanup, - smx_process_t process - ) +Context* UContextFactory::create_context(std::function code, + void_pfn_smxprocess_t cleanup, smx_process_t process) { if (sysv_parallel) - return new_context(code, argc, argv, cleanup, process); + return new_context(std::move(code), cleanup, process); else - return new_context(code, argc, argv, cleanup, process); + return new_context(std::move(code), cleanup, process); } -UContext::UContext(xbt_main_func_t code, - int argc, char **argv, - void_pfn_smxprocess_t cleanup_func, - smx_process_t process) - : Context(code, argc, argv, cleanup_func, process) +UContext::UContext(std::function code, + void_pfn_smxprocess_t cleanup_func, smx_process_t process) + : Context(std::move(code), cleanup_func, process) { /* if the user provided a function for the process then use it, otherwise it is the context for maestro */ - if (code) { + if (has_code()) { this->stack_ = (char*) SIMIX_context_stack_new(); getcontext(&this->uc_); this->uc_.uc_link = nullptr; diff --git a/src/simix/smx_private.h b/src/simix/smx_private.h index f161b9a23a..3dec962d8d 100644 --- a/src/simix/smx_private.h +++ b/src/simix/smx_private.h @@ -214,6 +214,11 @@ typedef struct s_smx_synchro { XBT_PRIVATE void SIMIX_context_mod_init(void); XBT_PRIVATE void SIMIX_context_mod_exit(void); +smx_context_t SIMIX_context_new( + xbt_main_func_t code, int argc, char **argv, + void_pfn_smxprocess_t cleanup_func, + smx_process_t simix_process); + #ifndef WIN32 XBT_PUBLIC_DATA(char sigsegv_stack[SIGSTKSZ]); #endif diff --git a/src/simix/smx_private.hpp b/src/simix/smx_private.hpp index a0d704aa9b..a6051cc82c 100644 --- a/src/simix/smx_private.hpp +++ b/src/simix/smx_private.hpp @@ -10,25 +10,6 @@ #include #include "smx_private.h" -/** - * \brief creates a new context for a user level process - * \param code a main function - * \param argc the number of arguments of the main function - * \param argv the vector of arguments of the main function - * \param cleanup_func the function to call when the context stops - * \param cleanup_arg the argument of the cleanup_func function - */ -static inline smx_context_t SIMIX_context_new(xbt_main_func_t code, - int argc, char **argv, - void_pfn_smxprocess_t cleanup_func, - smx_process_t simix_process) -{ - if (!simix_global) - xbt_die("simix is not initialized, please call MSG_init first"); - return simix_global->context_factory->create_context( - code, argc, argv, cleanup_func, simix_process); -} - /** * \brief destroy a context * \param context the context to destroy