Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Fix simcall_blocking returning a value.
authorArnaud Giersch <arnaud.giersch@univ-fcomte.fr>
Fri, 26 Mar 2021 13:40:24 +0000 (14:40 +0100)
committerArnaud Giersch <arnaud.giersch@univ-fcomte.fr>
Fri, 26 Mar 2021 14:06:57 +0000 (15:06 +0100)
Get the return value from observer->get_result().

include/simgrid/simix.hpp
src/s4u/s4u_Actor.cpp
src/s4u/s4u_ConditionVariable.cpp
src/s4u/s4u_Exec.cpp
src/s4u/s4u_Io.cpp
src/s4u/s4u_Mutex.cpp
src/s4u/s4u_Semaphore.cpp
src/simix/libsmx.cpp

index 9c62626..03e785c 100644 (file)
@@ -64,9 +64,6 @@ template <class F> typename std::result_of_t<F()> simcall(F&& code, mc::SimcallO
  * This is very similar to simcall() right above, but the calling actor will not get rescheduled until
  * actor->simcall_answer() is called explicitly.
  *
  * This is very similar to simcall() right above, but the calling actor will not get rescheduled until
  * actor->simcall_answer() is called explicitly.
  *
- * Since the return value does not come from the lambda directly, its type cannot be guessed automatically and must
- * be provided as template parameter.
- *
  * 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
  * 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
@@ -75,17 +72,25 @@ template <class F> typename std::result_of_t<F()> simcall(F&& code, mc::SimcallO
  * 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.
  * 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 R, class F> R simcall_blocking(F&& code, mc::SimcallObserver* observer = nullptr)
+template <class F> void simcall_blocking(F&& code, mc::SimcallObserver* observer = nullptr)
 {
   xbt_assert(not SIMIX_is_maestro(), "Cannot execute blocking call in kernel mode");
 
 {
   xbt_assert(not SIMIX_is_maestro(), "Cannot execute blocking call in kernel mode");
 
-  // If we are in the application, pass the code to the maestro which
-  // executes it for us and reports the result. We use a std::future which
+  // Pass the code to the maestro which executes it for us and reports the result. We use a std::future which
   // conveniently handles the success/failure value for us.
   // conveniently handles the success/failure value for us.
-  simgrid::xbt::Result<R> result;
+  simgrid::xbt::Result<void> result;
   simcall_run_blocking([&result, &code] { simgrid::xbt::fulfill_promise(result, std::forward<F>(code)); }, observer);
   simcall_run_blocking([&result, &code] { simgrid::xbt::fulfill_promise(result, std::forward<F>(code)); }, observer);
-  return result.get();
+  result.get(); // rethrow stored exception if any
+}
+
+template <class F, class Observer>
+auto simcall_blocking(F&& code, Observer* observer) -> decltype(observer->get_result())
+{
+  simcall_blocking(std::forward<F>(code), static_cast<mc::SimcallObserver*>(observer));
+  return observer->get_result();
 }
 } // namespace actor
 } // namespace kernel
 }
 } // namespace actor
 } // namespace kernel
index 6c2dbe9..d7a20c2 100644 (file)
@@ -114,7 +114,7 @@ void Actor::join(double timeout) const
 {
   kernel::actor::ActorImpl* issuer = kernel::actor::ActorImpl::self();
   const kernel::actor::ActorImpl* target = pimpl_;
 {
   kernel::actor::ActorImpl* issuer = kernel::actor::ActorImpl::self();
   const kernel::actor::ActorImpl* target = pimpl_;
-  kernel::actor::simcall_blocking<void>([issuer, target, timeout] {
+  kernel::actor::simcall_blocking([issuer, target, timeout] {
     if (target->finished_) {
       // The joined process is already finished, just wake up the issuer right away
       issuer->simcall_answer();
     if (target->finished_) {
       // The joined process is already finished, just wake up the issuer right away
       issuer->simcall_answer();
@@ -221,7 +221,7 @@ void Actor::suspend()
   kernel::actor::ActorImpl* issuer = kernel::actor::ActorImpl::self();
   kernel::actor::ActorImpl* target = pimpl_;
   s4u::Actor::on_suspend(*this);
   kernel::actor::ActorImpl* issuer = kernel::actor::ActorImpl::self();
   kernel::actor::ActorImpl* target = pimpl_;
   s4u::Actor::on_suspend(*this);
-  kernel::actor::simcall_blocking<void>([issuer, target]() {
+  kernel::actor::simcall_blocking([issuer, target]() {
     target->suspend();
     if (target != issuer) {
       /* If we are suspending ourselves, then just do not finish the simcall now */
     target->suspend();
     if (target != issuer) {
       /* If we are suspending ourselves, then just do not finish the simcall now */
@@ -322,7 +322,7 @@ void sleep_for(double duration)
     kernel::actor::ActorImpl* issuer = kernel::actor::ActorImpl::self();
     Actor::on_sleep(*issuer->get_ciface());
 
     kernel::actor::ActorImpl* issuer = kernel::actor::ActorImpl::self();
     Actor::on_sleep(*issuer->get_ciface());
 
-    kernel::actor::simcall_blocking<void>([issuer, duration]() {
+    kernel::actor::simcall_blocking([issuer, duration]() {
       if (MC_is_active() || MC_record_replay_is_active()) {
         MC_process_clock_add(issuer, duration);
         issuer->simcall_answer();
       if (MC_is_active() || MC_record_replay_is_active()) {
         MC_process_clock_add(issuer, duration);
         issuer->simcall_answer();
@@ -437,7 +437,7 @@ void suspend()
 {
   kernel::actor::ActorImpl* self = simgrid::kernel::actor::ActorImpl::self();
   s4u::Actor::on_suspend(*self->get_ciface());
 {
   kernel::actor::ActorImpl* self = simgrid::kernel::actor::ActorImpl::self();
   s4u::Actor::on_suspend(*self->get_ciface());
-  kernel::actor::simcall_blocking<void>([self] { self->suspend(); });
+  kernel::actor::simcall_blocking([self] { self->suspend(); });
 }
 
 void exit()
 }
 
 void exit()
index a59726f..877bfdd 100644 (file)
@@ -32,7 +32,7 @@ void ConditionVariable::wait(MutexPtr lock)
 {
   kernel::actor::ActorImpl* issuer = kernel::actor::ActorImpl::self();
   mc::ConditionWaitSimcall observer{issuer, pimpl_, lock->pimpl_};
 {
   kernel::actor::ActorImpl* issuer = kernel::actor::ActorImpl::self();
   mc::ConditionWaitSimcall observer{issuer, pimpl_, lock->pimpl_};
-  kernel::actor::simcall_blocking<void>(
+  kernel::actor::simcall_blocking(
       [&observer] { observer.get_cond()->wait(observer.get_mutex(), -1.0, observer.get_issuer()); }, &observer);
 }
 
       [&observer] { observer.get_cond()->wait(observer.get_mutex(), -1.0, observer.get_issuer()); }, &observer);
 }
 
@@ -40,7 +40,7 @@ void ConditionVariable::wait(const std::unique_lock<Mutex>& lock)
 {
   kernel::actor::ActorImpl* issuer = kernel::actor::ActorImpl::self();
   mc::ConditionWaitSimcall observer{issuer, pimpl_, lock.mutex()->pimpl_};
 {
   kernel::actor::ActorImpl* issuer = kernel::actor::ActorImpl::self();
   mc::ConditionWaitSimcall observer{issuer, pimpl_, lock.mutex()->pimpl_};
-  kernel::actor::simcall_blocking<void>(
+  kernel::actor::simcall_blocking(
       [&observer] { observer.get_cond()->wait(observer.get_mutex(), -1.0, observer.get_issuer()); }, &observer);
 }
 
       [&observer] { observer.get_cond()->wait(observer.get_mutex(), -1.0, observer.get_issuer()); }, &observer);
 }
 
@@ -52,10 +52,9 @@ std::cv_status s4u::ConditionVariable::wait_for(const std::unique_lock<Mutex>& l
 
   kernel::actor::ActorImpl* issuer = kernel::actor::ActorImpl::self();
   mc::ConditionWaitSimcall observer{issuer, pimpl_, lock.mutex()->pimpl_, timeout};
 
   kernel::actor::ActorImpl* issuer = kernel::actor::ActorImpl::self();
   mc::ConditionWaitSimcall observer{issuer, pimpl_, lock.mutex()->pimpl_, timeout};
-  kernel::actor::simcall_blocking<void>(
+  bool timed_out = kernel::actor::simcall_blocking(
       [&observer] { observer.get_cond()->wait(observer.get_mutex(), observer.get_timeout(), observer.get_issuer()); },
       &observer);
       [&observer] { observer.get_cond()->wait(observer.get_mutex(), observer.get_timeout(), observer.get_issuer()); },
       &observer);
-  bool timed_out = observer.get_result();
   if (timed_out) {
     // If we reached the timeout, we have to take the lock again:
     lock.mutex()->lock();
   if (timed_out) {
     // If we reached the timeout, we have to take the lock again:
     lock.mutex()->lock();
index 9d1a552..e0b9e3d 100644 (file)
@@ -41,7 +41,7 @@ Exec* Exec::wait_for(double timeout)
     vetoable_start();
 
   kernel::actor::ActorImpl* issuer = kernel::actor::ActorImpl::self();
     vetoable_start();
 
   kernel::actor::ActorImpl* issuer = kernel::actor::ActorImpl::self();
-  kernel::actor::simcall_blocking<void>([this, issuer, timeout] { this->get_impl()->wait_for(issuer, timeout); });
+  kernel::actor::simcall_blocking([this, issuer, timeout] { this->get_impl()->wait_for(issuer, timeout); });
   state_ = State::FINISHED;
   on_completion(*this);
   this->release_dependencies();
   state_ = State::FINISHED;
   on_completion(*this);
   this->release_dependencies();
@@ -56,12 +56,11 @@ int Exec::wait_any_for(std::vector<ExecPtr>* execs, double timeout)
 
   kernel::actor::ActorImpl* issuer = kernel::actor::ActorImpl::self();
   mc::ExecutionWaitanySimcall observer{issuer, &rexecs, timeout};
 
   kernel::actor::ActorImpl* issuer = kernel::actor::ActorImpl::self();
   mc::ExecutionWaitanySimcall observer{issuer, &rexecs, timeout};
-  kernel::actor::simcall_blocking<void>(
+  int changed_pos = kernel::actor::simcall_blocking(
       [&observer] {
         kernel::activity::ExecImpl::wait_any_for(observer.get_issuer(), observer.get_execs(), observer.get_timeout());
       },
       &observer);
       [&observer] {
         kernel::activity::ExecImpl::wait_any_for(observer.get_issuer(), observer.get_execs(), observer.get_timeout());
       },
       &observer);
-  int changed_pos = observer.get_result();
   if (changed_pos != -1) {
     on_completion(*(execs->at(changed_pos)));
     execs->at(changed_pos)->release_dependencies();
   if (changed_pos != -1) {
     on_completion(*(execs->at(changed_pos)));
     execs->at(changed_pos)->release_dependencies();
index 80423ea..aec4f16 100644 (file)
@@ -63,7 +63,7 @@ Io* Io::wait_for(double timeout)
     vetoable_start();
 
   kernel::actor::ActorImpl* issuer = kernel::actor::ActorImpl::self();
     vetoable_start();
 
   kernel::actor::ActorImpl* issuer = kernel::actor::ActorImpl::self();
-  kernel::actor::simcall_blocking<void>([this, issuer, timeout] { this->get_impl()->wait_for(issuer, timeout); });
+  kernel::actor::simcall_blocking([this, issuer, timeout] { this->get_impl()->wait_for(issuer, timeout); });
   state_ = State::FINISHED;
   this->release_dependencies();
 
   state_ = State::FINISHED;
   this->release_dependencies();
 
index dfcd612..184033d 100644 (file)
@@ -17,7 +17,7 @@ void Mutex::lock()
 {
   kernel::actor::ActorImpl* issuer = kernel::actor::ActorImpl::self();
   mc::MutexLockSimcall observer{issuer, pimpl_};
 {
   kernel::actor::ActorImpl* issuer = kernel::actor::ActorImpl::self();
   mc::MutexLockSimcall observer{issuer, pimpl_};
-  kernel::actor::simcall_blocking<void>([&observer] { observer.get_mutex()->lock(observer.get_issuer()); }, &observer);
+  kernel::actor::simcall_blocking([&observer] { observer.get_mutex()->lock(observer.get_issuer()); }, &observer);
 }
 
 /** @brief Release the ownership of the mutex, unleashing a blocked actor (if any)
 }
 
 /** @brief Release the ownership of the mutex, unleashing a blocked actor (if any)
index 90aaedf..7d42c3a 100644 (file)
@@ -24,17 +24,15 @@ void Semaphore::acquire()
 {
   kernel::actor::ActorImpl* issuer = kernel::actor::ActorImpl::self();
   mc::SemAcquireSimcall observer{issuer, pimpl_};
 {
   kernel::actor::ActorImpl* issuer = kernel::actor::ActorImpl::self();
   mc::SemAcquireSimcall observer{issuer, pimpl_};
-  kernel::actor::simcall_blocking<void>([&observer] { observer.get_sem()->acquire(observer.get_issuer(), -1.0); },
-                                        &observer);
+  kernel::actor::simcall_blocking([&observer] { observer.get_sem()->acquire(observer.get_issuer(), -1.0); }, &observer);
 }
 
 bool Semaphore::acquire_timeout(double timeout)
 {
   kernel::actor::ActorImpl* issuer = kernel::actor::ActorImpl::self();
   mc::SemAcquireSimcall observer{issuer, pimpl_, timeout};
 }
 
 bool Semaphore::acquire_timeout(double timeout)
 {
   kernel::actor::ActorImpl* issuer = kernel::actor::ActorImpl::self();
   mc::SemAcquireSimcall observer{issuer, pimpl_, timeout};
-  kernel::actor::simcall_blocking<void>(
+  return kernel::actor::simcall_blocking(
       [&observer] { observer.get_sem()->acquire(observer.get_issuer(), observer.get_timeout()); }, &observer);
       [&observer] { observer.get_sem()->acquire(observer.get_issuer(), observer.get_timeout()); }, &observer);
-  return observer.get_result();
 }
 
 void Semaphore::release()
 }
 
 void Semaphore::release()
index 98ec1f5..3ea6d4f 100644 (file)
@@ -36,8 +36,7 @@ simgrid::kernel::activity::State simcall_execution_wait(simgrid::kernel::activit
                                                         double timeout) // XBT_ATTRIB_DEPRECATED_v330
 {
   simgrid::kernel::actor::ActorImpl* issuer = simgrid::kernel::actor::ActorImpl::self();
                                                         double timeout) // XBT_ATTRIB_DEPRECATED_v330
 {
   simgrid::kernel::actor::ActorImpl* issuer = simgrid::kernel::actor::ActorImpl::self();
-  simgrid::kernel::actor::simcall_blocking<void>(
-      [execution, issuer, timeout] { execution->wait_for(issuer, timeout); });
+  simgrid::kernel::actor::simcall_blocking([execution, issuer, timeout] { execution->wait_for(issuer, timeout); });
   return simgrid::kernel::activity::State::DONE;
 }
 
   return simgrid::kernel::activity::State::DONE;
 }
 
@@ -45,8 +44,7 @@ simgrid::kernel::activity::State simcall_execution_wait(const simgrid::kernel::a
                                                         double timeout) // XBT_ATTRIB_DEPRECATED_v330
 {
   simgrid::kernel::actor::ActorImpl* issuer = simgrid::kernel::actor::ActorImpl::self();
                                                         double timeout) // XBT_ATTRIB_DEPRECATED_v330
 {
   simgrid::kernel::actor::ActorImpl* issuer = simgrid::kernel::actor::ActorImpl::self();
-  simgrid::kernel::actor::simcall_blocking<void>(
-      [execution, issuer, timeout] { execution->wait_for(issuer, timeout); });
+  simgrid::kernel::actor::simcall_blocking([execution, issuer, timeout] { execution->wait_for(issuer, timeout); });
   return simgrid::kernel::activity::State::DONE;
 }
 
   return simgrid::kernel::activity::State::DONE;
 }
 
@@ -66,13 +64,12 @@ unsigned int simcall_execution_waitany_for(simgrid::kernel::activity::ExecImpl*
   std::vector<simgrid::kernel::activity::ExecImpl*> execsv(execs, execs + count);
   simgrid::kernel::actor::ActorImpl* issuer = simgrid::kernel::actor::ActorImpl::self();
   simgrid::mc::ExecutionWaitanySimcall observer{issuer, &execsv, timeout};
   std::vector<simgrid::kernel::activity::ExecImpl*> execsv(execs, execs + count);
   simgrid::kernel::actor::ActorImpl* issuer = simgrid::kernel::actor::ActorImpl::self();
   simgrid::mc::ExecutionWaitanySimcall observer{issuer, &execsv, timeout};
-  simgrid::kernel::actor::simcall_blocking<void>(
+  return simgrid::kernel::actor::simcall_blocking(
       [&observer] {
         simgrid::kernel::activity::ExecImpl::wait_any_for(observer.get_issuer(), observer.get_execs(),
                                                           observer.get_timeout());
       },
       &observer);
       [&observer] {
         simgrid::kernel::activity::ExecImpl::wait_any_for(observer.get_issuer(), observer.get_execs(),
                                                           observer.get_timeout());
       },
       &observer);
-  return observer.get_result();
 }
 
 void simcall_process_join(smx_actor_t process, double timeout) // XBT_ATTRIB_DEPRECATED_v328
 }
 
 void simcall_process_join(smx_actor_t process, double timeout) // XBT_ATTRIB_DEPRECATED_v328
@@ -339,7 +336,7 @@ simgrid::kernel::activity::State simcall_io_wait(simgrid::kernel::activity::Acti
                                                  double timeout) // XBT_ATTRIB_DEPRECATED_v330
 {
   simgrid::kernel::actor::ActorImpl* issuer = simgrid::kernel::actor::ActorImpl::self();
                                                  double timeout) // XBT_ATTRIB_DEPRECATED_v330
 {
   simgrid::kernel::actor::ActorImpl* issuer = simgrid::kernel::actor::ActorImpl::self();
-  simgrid::kernel::actor::simcall_blocking<void>([io, issuer, timeout] { io->wait_for(issuer, timeout); });
+  simgrid::kernel::actor::simcall_blocking([io, issuer, timeout] { io->wait_for(issuer, timeout); });
   return simgrid::kernel::activity::State::DONE;
 }
 
   return simgrid::kernel::activity::State::DONE;
 }
 
@@ -347,7 +344,7 @@ simgrid::kernel::activity::State simcall_io_wait(const simgrid::kernel::activity
                                                  double timeout) // XBT_ATTRIB_DEPRECATED_v330
 {
   simgrid::kernel::actor::ActorImpl* issuer = simgrid::kernel::actor::ActorImpl::self();
                                                  double timeout) // XBT_ATTRIB_DEPRECATED_v330
 {
   simgrid::kernel::actor::ActorImpl* issuer = simgrid::kernel::actor::ActorImpl::self();
-  simgrid::kernel::actor::simcall_blocking<void>([io, issuer, timeout] { io->wait_for(issuer, timeout); });
+  simgrid::kernel::actor::simcall_blocking([io, issuer, timeout] { io->wait_for(issuer, timeout); });
   return simgrid::kernel::activity::State::DONE;
 }
 
   return simgrid::kernel::activity::State::DONE;
 }