- template <class R, class T>
- XBT_ATTRIB_DEPRECATED_v325("Please use a lambda or std::bind") static inline Timer* set(double date,
- R (*callback)(T*), T* arg)
- {
- return set(date, std::bind(callback, arg));
- }
+/** Execute some code (that does not return immediately) in kernel context
+ *
+ * This is very similar to simcall_answered() above, but the calling actor will not get rescheduled until
+ * actor->simcall_answer() is called explicitly.
+ *
+ * This is meant for blocking actions. For example, locking a mutex is a blocking simcall.
+ * First it's a simcall because that's obviously a modification of the world. Then, that's a blocking simcall because if
+ * the mutex happens not to be free, the actor is added to a queue of actors in the mutex. Every mutex->unlock() takes
+ * the first actor from the queue, mark it as current owner of the mutex and call actor->simcall_answer() to mark that
+ * this mutex is now unblocked and ready to run again. If the mutex is initially free, the calling actor is unblocked
+ * right away with actor->simcall_answer() once the mutex is marked as locked.
+ *
+ * If your code never calls actor->simcall_answer() itself, the actor will never return from its simcall.
+ *
+ * The return value is obtained from observer->get_result() if it exists. Otherwise void is returned.
+ */
+template <class F> void simcall_blocking(F&& code, SimcallObserver* observer = nullptr)
+{
+ xbt_assert(not s4u::Actor::is_maestro(), "Cannot execute blocking call in kernel mode");