Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[simix] Add comments about the generic simcalls and rename them
[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
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 }
175 }
176
177 /*
178  * Type of function that creates a process.
179  * The function must accept the following parameters:
180  * void* process: the process created will be stored there
181  * const char *name: a name for the object. It is for user-level information and can be NULL
182  * xbt_main_func_t code: is a function describing the behavior of the process
183  * void *data: data a pointer to any data one may want to attach to the new object.
184  * sg_host_t host: the location where the new process is executed
185  * int argc, char **argv: parameters passed to code
186  * xbt_dict_t pros: properties
187  */
188 typedef smx_process_t (*smx_creation_func_t) (
189                                       /* name */ const char*,
190                                       std::function<void()> code,
191                                       /* userdata */ void*,
192                                       /* hostname */ const char*,
193                                       /* kill_time */ double,
194                                       /* props */ xbt_dict_t,
195                                       /* auto_restart */ int,
196                                       /* parent_process */ smx_process_t);
197
198 extern "C"
199 XBT_PUBLIC(void) SIMIX_function_register_process_create(smx_creation_func_t function);
200
201 XBT_PUBLIC(smx_process_t) simcall_process_create(const char *name,
202                                           std::function<void()> code,
203                                           void *data,
204                                           const char *hostname,
205                                           double kill_time,
206                                           xbt_dict_t properties,
207                                           int auto_restart);
208
209 XBT_PUBLIC(smx_timer_t) SIMIX_timer_set(double date, std::packaged_task<void()> callback);
210
211 template<class F> inline
212 XBT_PUBLIC(smx_timer_t) SIMIX_timer_set(double date, F callback)
213 {
214   return SIMIX_timer_set(date, std::packaged_task<void()>(std::move(callback)));
215 }
216
217 template<class R, class T> inline
218 XBT_PUBLIC(smx_timer_t) SIMIX_timer_set(double date, R(*callback)(T*), T* arg)
219 {
220   return SIMIX_timer_set(date, [=](){ callback(arg); });
221 }
222
223 #endif