Logo AND Algorithmique Numérique Distribuée

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