Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
mark simix::Context as public to please windows
[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 #include <type_traits>
18
19 #include <xbt/function_types.h>
20 #include <simgrid/simix.h>
21
22 XBT_PUBLIC(void) simcall_run_kernel(std::function<void()> const& code);
23
24 namespace simgrid {
25 namespace simix {
26
27 /** Fulfill a promise by executing a given code */
28 template<class R, class F>
29 void fulfill_promise(std::promise<R>& promise, F&& code)
30 {
31   try {
32     promise.set_value(std::forward<F>(code)());
33   }
34   catch(...) {
35     promise.set_exception(std::current_exception());
36   }
37 }
38
39 /** Fulfill a promise by executing a given code
40  *
41  *  This is a special version for `std::promise<void>` because the default
42  *  version does not compile in this case.
43  */
44 template<class F>
45 void fulfill_promise(std::promise<void>& promise, F&& code)
46 {
47   try {
48     std::forward<F>(code)();
49     promise.set_value();
50   }
51   catch(...) {
52     promise.set_exception(std::current_exception());
53   }
54 }
55
56 /** Execute some code in the kernel/maestro
57  *
58  *  This can be used to enforce mutual exclusion with other simcall.
59  *  More importantly, this enforces a deterministic/reproducible ordering
60  *  of the operation with respect to other simcalls.
61  */
62 template<class F>
63 typename std::result_of<F()>::type kernel(F&& code)
64 {
65   // If we are in the maestro, we take the fast path and execute the
66   // code directly without simcall mashalling/unmarshalling/dispatch:
67   if (SIMIX_is_maestro())
68     return std::forward<F>(code)();
69
70   // If we are in the application, pass the code to the maestro which is
71   // executes it for us and reports the result. We use a std::future which
72   // conveniently handles the success/failure value for us.
73   typedef typename std::result_of<F()>::type R;
74   std::promise<R> promise;
75   simcall_run_kernel([&]{
76     xbt_assert(SIMIX_is_maestro(), "Not in maestro");
77     fulfill_promise(promise, std::forward<F>(code));
78   });
79   return promise.get_future().get();
80 }
81
82 class Context;
83 class ContextFactory;
84
85 XBT_PUBLIC_CLASS ContextFactory {
86 private:
87   std::string name_;
88 public:
89
90   ContextFactory(std::string name) : name_(std::move(name)) {}
91   virtual ~ContextFactory();
92   virtual Context* create_context(std::function<void()> code,
93     void_pfn_smxprocess_t cleanup, smx_process_t process) = 0;
94   virtual void run_all() = 0;
95   virtual Context* self();
96   std::string const& name() const
97   {
98     return name_;
99   }
100 private:
101   void declare_context(void* T, std::size_t size);
102 protected:
103   template<class T, class... Args>
104   T* new_context(Args&&... args)
105   {
106     T* context = new T(std::forward<Args>(args)...);
107     this->declare_context(context, sizeof(T));
108     return context;
109   }
110 };
111
112 XBT_PUBLIC_CLASS Context {
113 private:
114   std::function<void()> code_;
115   void_pfn_smxprocess_t cleanup_func_ = nullptr;
116   smx_process_t process_ = nullptr;
117 public:
118   bool iwannadie;
119 public:
120   Context(std::function<void()> code,
121           void_pfn_smxprocess_t cleanup_func,
122           smx_process_t process);
123   void operator()()
124   {
125     code_();
126   }
127   bool has_code() const
128   {
129     return (bool) code_;
130   }
131   smx_process_t process()
132   {
133     return this->process_;
134   }
135   void set_cleanup(void_pfn_smxprocess_t cleanup)
136   {
137     cleanup_func_ = cleanup;
138   }
139
140   // Virtual methods
141   virtual ~Context();
142   virtual void stop();
143   virtual void suspend() = 0;
144 };
145
146 }
147 }
148
149 #endif