Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[simix] Encapsulate main function, argc and argv in a closure
authorGabriel Corona <gabriel.corona@loria.fr>
Mon, 7 Dec 2015 15:58:50 +0000 (16:58 +0100)
committerGabriel Corona <gabriel.corona@loria.fr>
Tue, 8 Dec 2015 13:06:06 +0000 (14:06 +0100)
13 files changed:
include/simgrid/simix.hpp
src/bindings/java/JavaContext.cpp
src/bindings/java/JavaContext.hpp
src/msg/msg_process.c
src/simix/BoostContext.cpp
src/simix/BoostContext.hpp
src/simix/Context.cpp
src/simix/RawContext.cpp
src/simix/ThreadContext.cpp
src/simix/ThreadContext.hpp
src/simix/UContext.cpp
src/simix/smx_private.h
src/simix/smx_private.hpp

index 99f476f..3002a4b 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <utility>
 #include <memory>
+#include <functional>
 
 #include <xbt/function_types.h>
 #include <simgrid/simix.h>
@@ -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<void()> 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<void()> 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<void()> 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()
   {
index 12ebf6a..51ae35b 100644 (file)
@@ -41,10 +41,10 @@ JavaContext* JavaContextFactory::self()
 }
 
 JavaContext* JavaContextFactory::create_context(
-  xbt_main_func_t code, int argc, char ** argv,
+  std::function<void()> code,
   void_pfn_smxprocess_t cleanup, smx_process_t process)
 {
-  return this->new_context<JavaContext>(code, argc, argv, cleanup, process);
+  return this->new_context<JavaContext>(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<void()> 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);
index d773ad5..5649388 100644 (file)
@@ -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<void()> 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<void()> code,
+    void_pfn_smxprocess_t, smx_process_t process) override;
   void run_all() override;
 };
 
index 12c1edd..dd02f54 100644 (file)
@@ -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);
 }
 
index f2e5cee..aa35075 100644 (file)
@@ -25,11 +25,10 @@ namespace simix {
 
 class BoostSerialContext : public BoostContext {
 public:
-  BoostSerialContext(xbt_main_func_t code,
-      int argc, char **argv,
+  BoostSerialContext(std::function<void()> 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<void()> 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<void()>  code,
   void_pfn_smxprocess_t cleanup_func, smx_process_t process)
 {
   BoostContext* context = nullptr;
   if (BoostContext::parallel_)
 #ifdef CONTEXT_THREADS
     context = this->new_context<BoostParallelContext>(
-      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<BoostSerialContext>(
-      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<void()> 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:
index 4f64f41..d558d74 100644 (file)
@@ -43,8 +43,7 @@ protected:
   void* stack_ = nullptr;
 public:
   friend BoostContextFactory;
-  BoostContext(xbt_main_func_t code,
-          int argc, char **argv,
+  BoostContext(std::function<void()> 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<void()> code,
+    void_pfn_smxprocess_t, smx_process_t process) override;
   void run_all() override;
 };
 
index fbfffc9..e6eec95 100644 (file)
@@ -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 <vector>
+#include <string>
+#include <cstring>
+#include <memory>
+
 #include <simgrid/simix.hpp>
 
 #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<void()> wrap_main(xbt_main_func_t code, int argc, char **argv)
+{
+  if (code) {
+    auto arg = std::make_shared<simgrid::simix::args>(argc, argv);
+    return [=]() {
+      code(arg->argc(), arg->argv());
+    };
+  } else return std::function<void()>();
+}
+
+/**
+ * \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<void()> 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()
index 6247479..8aefa71 100644 (file)
@@ -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<void()> 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<void()> 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<void()> code,
+    void_pfn_smxprocess_t cleanup, smx_process_t process)
 {
-  return this->new_context<RawContext>(code, argc, argv,
+  return this->new_context<RawContext>(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<void()> 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,
index 19be3d4..de4e718 100644 (file)
@@ -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<void()> code,
+    void_pfn_smxprocess_t cleanup, smx_process_t process)
 {
-  return this->new_context<ThreadContext>(code, argc, argv, cleanup, process);
+  return this->new_context<ThreadContext>(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<void()> 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)
index 4ecd959..f0655b1 100644 (file)
@@ -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<void()> 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<void()> code,
+    void_pfn_smxprocess_t cleanup_func,  smx_process_t process) override;
   void run_all() override;
   ThreadContext* self() override;
 };
index a5e8e8f..d2ce507 100644 (file)
@@ -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<void()>  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<void()>  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<void()>  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<void()> 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<void()> code,
+  void_pfn_smxprocess_t cleanup, smx_process_t process)
 {
   if (sysv_parallel)
-    return new_context<ParallelUContext>(code, argc, argv, cleanup, process);
+    return new_context<ParallelUContext>(std::move(code), cleanup, process);
   else
-    return new_context<SerialUContext>(code, argc, argv, cleanup, process);
+    return new_context<SerialUContext>(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<void()> 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;
index f161b9a..3dec962 100644 (file)
@@ -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
index a0d704a..a6051cc 100644 (file)
 #include <simgrid/simix.hpp>
 #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