Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[simix] Pass the code by reference in simcall_run_kernel
[simgrid.git] / include / simgrid / simix.hpp
1 /* Copyright (c) 2007-2010, 2012-2015. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5  * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 #ifndef SIMGRID_SIMIX_HPP
8 #define SIMGRID_SIMIX_HPP
9
10 #include <cstddef>
11
12 #include <exception>
13 #include <string>
14 #include <utility>
15 #include <memory>
16 #include <functional>
17 #include <future>
18 #include <type_traits>
19
20 #include <xbt/function_types.h>
21 #include <xbt/future.hpp>
22
23 #include <simgrid/simix.h>
24
25 XBT_PUBLIC(void) simcall_run_kernel(std::function<void()> const& code);
26
27 template<class F> inline
28 void simcall_run_kernel(F& f)
29 {
30   simcall_run_kernel(std::function<void()>(std::ref(f)));
31 }
32
33 namespace simgrid {
34 namespace simix {
35
36 /** Execute some code in the kernel/maestro
37  *
38  *  This can be used to enforce mutual exclusion with other simcall.
39  *  More importantly, this enforces a deterministic/reproducible ordering
40  *  of the operation with respect to other simcalls.
41  */
42 template<class F>
43 typename std::result_of<F()>::type kernel(F&& code)
44 {
45   // If we are in the maestro, we take the fast path and execute the
46   // code directly without simcall mashalling/unmarshalling/dispatch:
47   if (SIMIX_is_maestro())
48     return std::forward<F>(code)();
49
50   // If we are in the application, pass the code to the maestro which
51   // executes it for us and reports the result. We use a std::future which
52   // conveniently handles the success/failure value for us.
53   typedef typename std::result_of<F()>::type R;
54   simgrid::xbt::Result<R> result;
55   simcall_run_kernel([&]{
56     xbt_assert(SIMIX_is_maestro(), "Not in maestro");
57     simgrid::xbt::fulfillPromise(result, std::forward<F>(code));
58   });
59   return result.get();
60 }
61
62 class Context;
63 class ContextFactory;
64
65 XBT_PUBLIC_CLASS ContextFactory {
66 private:
67   std::string name_;
68 public:
69
70   explicit ContextFactory(std::string name) : name_(std::move(name)) {}
71   virtual ~ContextFactory();
72   virtual Context* create_context(std::function<void()> code,
73     void_pfn_smxprocess_t cleanup, smx_process_t process) = 0;
74
75   // Optional methods for attaching main() as a context:
76
77   /** Creates a context from the current context of execution
78    *
79    *  This will not work on all implementation of `ContextFactory`.
80    */
81   virtual Context* attach(void_pfn_smxprocess_t cleanup_func, smx_process_t process);
82   virtual Context* create_maestro(std::function<void()> code, smx_process_t process);
83
84   virtual void run_all() = 0;
85   virtual Context* self();
86   std::string const& name() const
87   {
88     return name_;
89   }
90 private:
91   void declare_context(void* T, std::size_t size);
92 protected:
93   template<class T, class... Args>
94   T* new_context(Args&&... args)
95   {
96     T* context = new T(std::forward<Args>(args)...);
97     this->declare_context(context, sizeof(T));
98     return context;
99   }
100 };
101
102 XBT_PUBLIC_CLASS Context {
103 private:
104   std::function<void()> code_;
105   void_pfn_smxprocess_t cleanup_func_ = nullptr;
106   smx_process_t process_ = nullptr;
107 public:
108   bool iwannadie;
109 public:
110   Context(std::function<void()> code,
111           void_pfn_smxprocess_t cleanup_func,
112           smx_process_t process);
113   void operator()()
114   {
115     code_();
116   }
117   bool has_code() const
118   {
119     return (bool) code_;
120   }
121   smx_process_t process()
122   {
123     return this->process_;
124   }
125   void set_cleanup(void_pfn_smxprocess_t cleanup)
126   {
127     cleanup_func_ = cleanup;
128   }
129
130   // Virtual methods
131   virtual ~Context();
132   virtual void stop();
133   virtual void suspend() = 0;
134 };
135
136 XBT_PUBLIC_CLASS AttachContext : public Context {
137 public:
138
139   AttachContext(std::function<void()> code,
140           void_pfn_smxprocess_t cleanup_func,
141           smx_process_t process)
142     : Context(std::move(code), cleanup_func, process)
143   {}
144
145   ~AttachContext() override;
146
147   /** Called by the context when it is ready to give control
148    *  to the maestro.
149    */
150   virtual void attach_start() = 0;
151
152   /** Called by the context when it has finished its job */
153   virtual void attach_stop() = 0;
154 };
155
156 XBT_PUBLIC(void) set_maestro(std::function<void()> code);
157 XBT_PUBLIC(void) create_maestro(std::function<void()> code);
158
159 }
160 }
161
162 /*
163  * Type of function that creates a process.
164  * The function must accept the following parameters:
165  * void* process: the process created will be stored there
166  * const char *name: a name for the object. It is for user-level information and can be NULL
167  * xbt_main_func_t code: is a function describing the behavior of the process
168  * void *data: data a pointer to any data one may want to attach to the new object.
169  * sg_host_t host: the location where the new process is executed
170  * int argc, char **argv: parameters passed to code
171  * xbt_dict_t pros: properties
172  */
173 typedef smx_process_t (*smx_creation_func_t) (
174                                       /* name */ const char*,
175                                       std::function<void()> code,
176                                       /* userdata */ void*,
177                                       /* hostname */ const char*,
178                                       /* kill_time */ double,
179                                       /* props */ xbt_dict_t,
180                                       /* auto_restart */ int,
181                                       /* parent_process */ smx_process_t);
182
183 extern "C"
184 XBT_PUBLIC(void) SIMIX_function_register_process_create(smx_creation_func_t function);
185
186 XBT_PUBLIC(smx_process_t) simcall_process_create(const char *name,
187                                           std::function<void()> code,
188                                           void *data,
189                                           const char *hostname,
190                                           double kill_time,
191                                           xbt_dict_t properties,
192                                           int auto_restart);
193
194 XBT_PUBLIC(smx_timer_t) SIMIX_timer_set(double date, std::function<void()> callback);
195
196 template<class R, class T> inline
197 XBT_PUBLIC(smx_timer_t) SIMIX_timer_set(double date, R(*callback)(T*), T* arg)
198 {
199   return SIMIX_timer_set(date, [=](){ callback(arg); });
200 }
201
202 #endif