Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Add a missing file to the archive
[simgrid.git] / include / simgrid / simix / blocking_simcall.hpp
1 /* Copyright (c) 2016. 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_BLOCKING_SIMCALL_HPP
8 #define SIMGRID_SIMIX_BLOCKING_SIMCALL_HPP
9
10 #include <iostream>
11
12 #include <exception>
13
14 #include <xbt/sysdep.h>
15
16 #include <future>
17
18 #include <xbt/future.hpp>
19 #include <simgrid/kernel/future.hpp>
20 #include <simgrid/simix.h>
21
22 XBT_PUBLIC(void) simcall_run_blocking(std::function<void()> const& code);
23
24 namespace simgrid {
25 namespace simix {
26
27 XBT_PUBLIC(void) unblock(smx_process_t process);
28
29 /** Execute some code in kernel mode and wakes up the process when
30  *  the result is available.
31  *
32  *  The code given is executed in SimGrid kernel and expected to return
33  *  a `simgrid::kernel::Future`. The current process is resumed whenever
34  *  the Future becomes ready and gets the value or exception of the future:
35  *
36  *  This can be used to implement blocking calls in without adding new simcalls.
37  *  One downside of this approach is that we don't have any semantic on what
38  *  the process is waiting. This might be a problem for the model-checker and
39  *  we'll have to device a way to make it work.
40  *
41  *  @param     code Kernel code returning a `simgrid::kernel::Future<T>`
42  *  @return         Value of the kernel future
43  *  @exception      Exception from the kernel future
44  */
45 template<class F>
46 auto blocking_simcall(F code) -> decltype(code().get())
47 {
48   typedef decltype(code().get()) T;
49   if (SIMIX_is_maestro())
50     xbt_die("Can't execute blocking call in kernel mode");
51
52   smx_process_t self = SIMIX_process_self();
53   simgrid::xbt::Result<T> result;
54
55   simcall_run_blocking([&result, self, &code]{
56     try {
57       auto future = code();
58       future.then([&result, self](simgrid::kernel::Future<T> value) {
59         simgrid::xbt::setPromise(result, value);
60         simgrid::simix::unblock(self);
61       });
62     }
63     catch (...) {
64       result.set_exception(std::current_exception());
65       simgrid::simix::unblock(self);
66     }
67   });
68   return result.get();
69 }
70
71 }
72 }
73
74 #endif