Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Add new entry in Release_Notes.
[simgrid.git] / doc / doxygen / inside_extending.doc
1 /**
2 @page inside_extending Extending SimGrid
3
4 @tableofcontents
5
6 @section simgrid_dev_guide_generic_simcall The modern SimCall interface
7
8 We now have some generic simcalls which can be used to interface with the
9 Maestro without creating new simcalls. You might want to use them instead of
10 the defining additional simcalls.  The long term goal is to replace most of
11 the simcalls with the generic ones.
12
13 For simcalls which never block, `kernelImmediate()` can be used. It takes a
14 C++ callback executes it in maestro. Any value returned by the callback is
15 returned by `kernelImmediate()`. Conversely, if the callback throws an
16 exception, this exception is propagated out of `kernelImmediate()`. Executing
17 the code in maestro enforces mutual exclusion (no other user process is running)
18 and enforce a deterministic order which guarantees the reproducibility of the
19 simulation.  This call is particularly useful for implementing mutable calls:
20
21 ~~~
22 void Host::setProperty(const char*key, const char *value){
23   simgrid::simix::kernelImmediate([&] {
24     simgrid::kernel::resource::HostImpl* host =
25        this->extension<simgrid::kernel::resource::HostImpl>();
26     host->setProperty(key,value);
27   });
28 }
29 ~~~
30
31 If there is no blocking and no mutation involved (getters), you might consider
32 avoiding switching to Maestro and reading directly the data you're interested
33 in.
34
35 For simcalls which might block, `kernel_sync()` can be used. It takes a
36 C++ callback and executes it immediately in maestro. This C++ callback is
37 expected to return a `simgrid::kernel::Future<T>` reprensenting the operation
38 in the kernel. When the operations completes, the user process is waken up
39 with the result:
40
41 ~~~
42 try {
43   std::vector<char> result = simgrid::simix::kernel_sync([&] {
44     // Fictional example, simgrid::kernel::readFile does not exist.
45     simgrid::kernel::Future<std::vector<char>> result = simgrid::kernel::readFile(file);
46     return result;
47   });
48   XBT_DEBUG("Finished reading file %s: length %zu", file, result.size());
49 }
50 // If the operation failed, kernel_sync() throws an exception:
51 catch (std::runtime_error& e) {
52   XBT_ERROR("Could not read file %s", file);
53 }
54 ~~~
55
56 Asynchronous blocks can be implemented with `kernel_async()`. It works
57 like `kernel_sync()` but does not block. Instead, it returns a
58 `simgrid::simix::Future` representing the operation in the process:
59
60 ~~~
61 simgrid::simix::Future<std:vector<char>> result = simgrid::simix::kernel_sync([&] {
62   // Fictional example, simgrid::kernel::readFile does not exist.
63   simgrid::kernek::Future<std::vector<char>> result = simgrid::kernel::readFile(file);
64   return result;
65 };
66
67 // Do some work while the operation is pending:
68 while (!result.is_ready() && hasWorkToDo())
69   doMoreWork();
70
71 // We don't have anything to do, wait for the operation to complete and
72 // get its value:
73 try {
74   std:vector<char> data = result.get();
75   XBT_DEBUG("Finished reading file %s: length %zu", file, data.size());
76 }
77 // If the operation failed, .get() throws an exception:
78 catch (std::runtime_error& e) {
79   XBT_ERROR("Could not read file %s", file);
80 }
81 ~~~
82
83 <b>Note:</b> `kernel_sync(f)` could be implemented as `kernel_async(f).get()`.
84
85 */