Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[s4u] Mailbox::receiver return a s4u::ActorPtr
[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 <string>
13 #include <utility>
14 #include <memory>
15 #include <functional>
16
17 #include <xbt/function_types.h>
18 #include <xbt/future.hpp>
19 #include <xbt/functional.hpp>
20
21 #include <simgrid/simix.h>
22
23 XBT_PUBLIC(void) simcall_run_kernel(std::function<void()> const& code);
24
25 /** Execute some code in the kernel and block
26  *
27  * run_blocking() is a generic blocking simcall. It is given a callback
28  * which is executed immediately in the SimGrid kernel. The callback is
29  * responsible for setting the suitable logic for waking up the process
30  * when needed.
31  *
32  * @ref simix::kernelSync() is a higher level wrapper for this.
33  */
34 XBT_PUBLIC(void) simcall_run_blocking(std::function<void()> const& code);
35
36 template<class F> inline
37 void simcall_run_kernel(F& f)
38 {
39   simcall_run_kernel(std::function<void()>(std::ref(f)));
40 }
41 template<class F> inline
42 void simcall_run_blocking(F& f)
43 {
44   simcall_run_blocking(std::function<void()>(std::ref(f)));
45 }
46
47 namespace simgrid {
48
49 namespace simix {
50
51 /** Execute some code in the kernel/maestro
52  *
53  *  This can be used to enforce mutual exclusion with other simcall.
54  *  More importantly, this enforces a deterministic/reproducible ordering
55  *  of the operation with respect to other simcalls.
56  */
57 template<class F>
58 typename std::result_of<F()>::type kernelImmediate(F&& code)
59 {
60   // If we are in the maestro, we take the fast path and execute the
61   // code directly without simcall mashalling/unmarshalling/dispatch:
62   if (SIMIX_is_maestro())
63     return std::forward<F>(code)();
64
65   // If we are in the application, pass the code to the maestro which
66   // executes it for us and reports the result. We use a std::future which
67   // conveniently handles the success/failure value for us.
68   typedef typename std::result_of<F()>::type R;
69   simgrid::xbt::Result<R> result;
70   simcall_run_kernel([&]{
71     xbt_assert(SIMIX_is_maestro(), "Not in maestro");
72     simgrid::xbt::fulfillPromise(result, std::forward<F>(code));
73   });
74   return result.get();
75 }
76
77 class Context;
78 class ContextFactory;
79
80 XBT_PUBLIC_CLASS ContextFactory {
81 private:
82   std::string name_;
83 public:
84
85   explicit ContextFactory(std::string name) : name_(std::move(name)) {}
86   virtual ~ContextFactory();
87   virtual Context* create_context(std::function<void()> code,
88     void_pfn_smxprocess_t cleanup, smx_process_t process) = 0;
89
90   // Optional methods for attaching main() as a context:
91
92   /** Creates a context from the current context of execution
93    *
94    *  This will not work on all implementation of `ContextFactory`.
95    */
96   virtual Context* attach(void_pfn_smxprocess_t cleanup_func, smx_process_t process);
97   virtual Context* create_maestro(std::function<void()> code, smx_process_t process);
98
99   virtual void run_all() = 0;
100   virtual Context* self();
101   std::string const& name() const
102   {
103     return name_;
104   }
105 private:
106   void declare_context(void* T, std::size_t size);
107 protected:
108   template<class T, class... Args>
109   T* new_context(Args&&... args)
110   {
111     T* context = new T(std::forward<Args>(args)...);
112     this->declare_context(context, sizeof(T));
113     return context;
114   }
115 };
116
117 XBT_PUBLIC_CLASS Context {
118 private:
119   std::function<void()> code_;
120   void_pfn_smxprocess_t cleanup_func_ = nullptr;
121   smx_process_t process_ = nullptr;
122 public:
123   bool iwannadie;
124 public:
125   Context(std::function<void()> code,
126           void_pfn_smxprocess_t cleanup_func,
127           smx_process_t process);
128   void operator()()
129   {
130     code_();
131   }
132   bool has_code() const
133   {
134     return (bool) code_;
135   }
136   smx_process_t process()
137   {
138     return this->process_;
139   }
140   void set_cleanup(void_pfn_smxprocess_t cleanup)
141   {
142     cleanup_func_ = cleanup;
143   }
144
145   // Virtual methods
146   virtual ~Context();
147   virtual void stop();
148   virtual void suspend() = 0;
149 };
150
151 XBT_PUBLIC_CLASS AttachContext : public Context {
152 public:
153
154   AttachContext(std::function<void()> code,
155           void_pfn_smxprocess_t cleanup_func,
156           smx_process_t process)
157     : Context(std::move(code), cleanup_func, process)
158   {}
159
160   ~AttachContext() override;
161
162   /** Called by the context when it is ready to give control
163    *  to the maestro.
164    */
165   virtual void attach_start() = 0;
166
167   /** Called by the context when it has finished its job */
168   virtual void attach_stop() = 0;
169 };
170
171 XBT_PUBLIC(void) set_maestro(std::function<void()> code);
172 XBT_PUBLIC(void) create_maestro(std::function<void()> code);
173
174 // What's executed as SIMIX actor code:
175 typedef std::function<void()> ActorCode;
176
177 // Create ActorCode based on argv:
178 typedef std::function<ActorCode(std::vector<std::string> args)> ActorCodeFactory;
179
180 XBT_PUBLIC(void) registerFunction(const char* name, ActorCodeFactory factory);
181
182 }
183 }
184
185 /*
186  * Type of function that creates a process.
187  * The function must accept the following parameters:
188  * void* process: the process created will be stored there
189  * const char *name: a name for the object. It is for user-level information and can be NULL
190  * xbt_main_func_t code: is a function describing the behavior of the process
191  * void *data: data a pointer to any data one may want to attach to the new object.
192  * sg_host_t host: the location where the new process is executed
193  * int argc, char **argv: parameters passed to code
194  * xbt_dict_t pros: properties
195  */
196 typedef smx_process_t (*smx_creation_func_t) (
197                                       /* name */ const char*,
198                                       std::function<void()> code,
199                                       /* userdata */ void*,
200                                       /* hostname */ const char*,
201                                       /* kill_time */ double,
202                                       /* props */ xbt_dict_t,
203                                       /* auto_restart */ int,
204                                       /* parent_process */ smx_process_t);
205
206 extern "C"
207 XBT_PUBLIC(void) SIMIX_function_register_process_create(smx_creation_func_t function);
208
209 XBT_PUBLIC(smx_process_t) simcall_process_create(const char *name,
210                                           std::function<void()> code,
211                                           void *data,
212                                           const char *hostname,
213                                           double kill_time,
214                                           xbt_dict_t properties,
215                                           int auto_restart);
216
217 XBT_PUBLIC(smx_timer_t) SIMIX_timer_set(double date, simgrid::xbt::Task<void()> callback);
218
219 template<class F> inline
220 XBT_PUBLIC(smx_timer_t) SIMIX_timer_set(double date, F callback)
221 {
222   return SIMIX_timer_set(date, simgrid::xbt::Task<void()>(std::move(callback)));
223 }
224
225 template<class R, class T> inline
226 XBT_PUBLIC(smx_timer_t) SIMIX_timer_set(double date, R(*callback)(T*), T* arg)
227 {
228   return SIMIX_timer_set(date, [=](){ callback(arg); });
229 }
230
231 #endif