mandatory to the model-checker. The simcalls, representing actors'
actions, are the transitions of the formal system. Verifying the
system requires to manipulate these transitions explicitly. This also
-allows to run safely the actors in parallel, even if this is less
+allows one to run the actors safely in parallel, even if this is less
commonly used by our users.
So, the key ideas here are:
@code{cpp}
struct s_smx_simcall {
// Simcall number:
- e_smx_simcall_t call;
+ Simcall call;
// Issuing actor:
smx_actor_t issuer;
// Arguments of the simcall:
`simgrid::simix::unblock(actor)`) when the operation is completed.
This is wrapped in a higher-level primitive as well. The
-`kernelSync()` function expects a function-object which is executed
+`kernel_sync()` function expects a function-object which is executed
immediately in the simulation kernel and returns a `Future<T>`. The
simulator blocks the actor and resumes it when the `Future<T>` becomes
ready with its result:
@code{cpp}
template<class F>
-auto kernelSync(F code) -> decltype(code().get())
+auto kernel_sync(F code) -> decltype(code().get())
{
typedef decltype(code().get()) T;
if (SIMIX_is_maestro())
A contrived example of this would be:
@code{cpp}
-int res = simgrid::simix::kernelSync([&] {
+int res = simgrid::simix::kernel_sync([&] {
return kernel_wait_until(30).then(
[](simgrid::kernel::Future<void> future) {
return 42;
### Asynchronous operations {#uhood_switch_v2_async}
-We can write the related `kernelAsync()` which wakes up the actor immediately
+We can write the related `kernel_async()` which wakes up the actor immediately
and returns a future to the actor. As this future is used in the actor context,
it is a different future
(`simgrid::simix::Future` instead of `simgrid::kernel::Future`)
}
@endcode
-`kernelAsync()` simply :wink: calls `kernelImmediate()` and wraps the
+`kernel_async()` simply :wink: calls `kernelImmediate()` and wraps the
`simgrid::kernel::Future` into a `simgrid::simix::Future`:
@code{cpp}
template<class F>
-auto kernelAsync(F code)
+auto kernel_async(F code)
-> Future<decltype(code().get())>
{
typedef decltype(code().get()) T;
A contrived example of this would be:
@code{cpp}
-simgrid::simix::Future<int> future = simgrid::simix::kernelSync([&] {
+simgrid::simix::Future<int> future = simgrid::simix::kernel_sync([&] {
return kernel_wait_until(30).then(
[](simgrid::kernel::Future<void> future) {
return 42;
int res = future.get();
@endcode
-`kernelSync()` could be rewritten as:
+`kernel_sync()` could be rewritten as:
@code{cpp}
template<class F>
-auto kernelSync(F code) -> decltype(code().get())
+auto kernel_sync(F code) -> decltype(code().get())
{
- return kernelAsync(std::move(code)).get();
+ return kernel_async(std::move(code)).get();
}
@endcode
The semantic is equivalent but this form would require two simcalls
-instead of one to do the same job (one in `kernelAsync()` and one in
+instead of one to do the same job (one in `kernel_async()` and one in
`.get()`).
## Mutexes and condition variables
simcall_cond_wait_timeout(cond_, lock.mutex()->mutex_, timeout);
return std::cv_status::no_timeout;
}
- catch (xbt_ex& e) {
-
+ catch (const simgrid::TimeoutException& e) {
// If the exception was a timeout, we have to take the lock again:
- if (e.category == timeout_error) {
- try {
- lock.mutex()->lock();
- return std::cv_status::timeout;
- }
- catch (...) {
- std::terminate();
- }
+ try {
+ lock.mutex()->lock();
+ return std::cv_status::timeout;
+ }
+ catch (...) {
+ std::terminate();
}
-
- std::terminate();
}
catch (...) {
std::terminate();
* the second one is a wait-based (`future.get()`) future used in the actors
which waits using a simcall.
-These futures are used to implement `kernelSync()` and `kernelAsync()` which
+These futures are used to implement `kernel_sync()` and `kernel_async()` which
expose asynchronous operations in the simulation kernel to the actors.
In addition, we wrote variations of some other C++ standard library
This type of approach might be useful for other libraries which define
their own contexts. An example of this is
-[Mordor](https://github.com/mozy/mordor), a I/O library using fibers
+[Mordor](https://github.com/mozy/mordor), an I/O library using fibers
(cooperative scheduling): it implements cooperative/fiber
[mutex](https://github.com/mozy/mordor/blob/4803b6343aee531bfc3588ffc26a0d0fdf14b274/mordor/fibersynchronization.h#L70),
[recursive
@code{cpp}
template<class T>
class Result {
- enum class ResultStatus {
- invalid,
- value,
- exception,
- };
public:
- Result();
- ~Result();
- Result(Result const& that);
- Result& operator=(Result const& that);
- Result(Result&& that);
- Result& operator=(Result&& that);
bool is_valid() const;
- void reset();
void set_exception(std::exception_ptr e);
void set_value(T&& value);
void set_value(T const& value);
T get();
private:
- ResultStatus status_ = ResultStatus::invalid;
- union {
- T value_;
- std::exception_ptr exception_;
- };
+ boost::variant<boost::blank, T, std::exception_ptr> value_;
};
@endcode~
in the simulation which we would like to avoid.
`std::try_lock()` should be safe to use though.
-*/
\ No newline at end of file
+*/