Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[sonar] Initialize data members with class initializers, or initialization lists.
[simgrid.git] / include / simgrid / kernel / future.hpp
index 581db40..c55f741 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016. The SimGrid Team.
+/* Copyright (c) 2016-2019. The SimGrid Team.
  * All rights reserved.                                                     */
 
 /* This program is free software; you can redistribute it and/or modify it
@@ -48,7 +48,7 @@ public:
   FutureStateBase(FutureStateBase const&) = delete;
   FutureStateBase& operator=(FutureStateBase const&) = delete;
 
-  XBT_PUBLIC(void) schedule(simgrid::xbt::Task<void()>&& job);
+  XBT_PUBLIC void schedule(simgrid::xbt::Task<void()>&& job);
 
   void set_exception(std::exception_ptr exception)
   {
@@ -74,7 +74,7 @@ public:
       schedule(std::move(continuation));
       break;
     case FutureStatus::not_ready:
-      // The future is not ready so we mast keep the continuation for
+      // The future is not ready so we must keep the continuation for
       // executing it later:
       continuation_ = std::move(continuation);
       break;
@@ -103,7 +103,7 @@ protected:
     status_ = FutureStatus::ready;
     if (continuation_) {
       // We unregister the continuation before executing it.
-      // We need to do this becase the current implementation of the
+      // We need to do this because the current implementation of the
       // continuation has a shared_ptr to the FutureState.
       auto continuation = std::move(continuation_);
       this->schedule(std::move(continuation));
@@ -135,14 +135,13 @@ private:
 /** Shared state for future and promises
  *
  *  You are not expected to use them directly but to create them
- *  implicitely through a @ref simgrid::kernel::Promise.
+ *  implicitly through a @ref simgrid::kernel::Promise.
  *  Alternatively kernel operations could inherit or contain FutureState
- *  if they are managed with @ref std::shared_ptr.
+ *  if they are managed with std::shared_ptr.
  **/
 template<class T>
 class FutureState : public FutureStateBase {
 public:
-
   void set_value(T value)
   {
     if (this->get_status() != FutureStatus::not_ready)
@@ -157,7 +156,7 @@ public:
     xbt_assert(this->value_);
     auto result = std::move(this->value_.get());
     this->value_ = boost::optional<T>();
-    return std::move(result);
+    return result;
   }
 
 private:
@@ -181,7 +180,7 @@ public:
     xbt_assert(this->value_);
     T* result = value_;
     value_ = nullptr;
-    return *value_;
+    return *result;
   }
 
 private:
@@ -204,32 +203,29 @@ public:
   }
 };
 
-template<class T>
-void bindPromise(Promise<T> promise, Future<T> future)
+template <class T> void bind_promise(Promise<T>&& promise, Future<T> future)
 {
-  struct PromiseBinder {
+  class PromiseBinder {
   public:
-    explicit PromiseBinder(Promise<T> promise) : promise_(std::move(promise)) {}
-    void operator()(Future<T> future)
-    {
-      simgrid::xbt::setPromise(promise_, future);
-    }
+    explicit PromiseBinder(Promise<T>&& promise) : promise_(std::move(promise)) {}
+    void operator()(Future<T> future) { simgrid::xbt::set_promise(promise_, future); }
+
   private:
     Promise<T> promise_;
   };
   future.then_(PromiseBinder(std::move(promise)));
 }
 
-template<class T> Future<T> unwrapFuture(Future<Future<T>> future);
+template <class T> Future<T> unwrap_future(Future<Future<T>> future);
 
 /** Result of some (probably) asynchronous operation in the SimGrid kernel
  *
  * @ref simgrid::simix::Future and @ref simgrid::simix::Future provide an
- * abstration for asynchronous stuff happening in the SimGrid kernel. They
+ * abstraction for asynchronous stuff happening in the SimGrid kernel. They
  * are based on C++1z futures.
  *
  * The future represents a value which will be available at some point when this
- * asynchronous operaiont is finished. Alternatively, if this operations fails,
+ * asynchronous operation is finished. Alternatively, if this operations fails,
  * the result of the operation might be an exception.
  *
  *  As the operation is possibly no terminated yet, we cannot get the result
@@ -250,7 +246,7 @@ template<class T> Future<T> unwrapFuture(Future<Future<T>> future);
  *    // available:
  *    try {
  *      // Try to get value, this might throw an exception if the operation
- *      // failed (such as an exception throwed by the worker process):
+ *      // failed (such as an exception thrown by the worker process):
  *      std::string value = result.get();
  *      XBT_INFO("Value: %s", value.c_str());
  *    }
@@ -261,7 +257,7 @@ template<class T> Future<T> unwrapFuture(Future<Future<T>> future);
  *  );
  *  </pre>
  *
- *  This is based on C++1z @ref std::future but with some differences:
+ *  This is based on C++1z std::future but with some differences:
  *
  *  * there is no thread synchronization (atomic, mutex, condition variable,
  *    etc.) because everything happens in the SimGrid event loop;
@@ -271,7 +267,7 @@ template<class T> Future<T> unwrapFuture(Future<Future<T>> future);
  *  * inside the `.then()`, `.get()` can be used;
  *
  *  * `.get()` can only be used when `.is_ready()` (as everything happens in
- *     a single-thread, the future would be guaranted to deadlock if `.get()`
+ *     a single-thread, the future would be guaranteed to deadlock if `.get()`
  *     is called when the future is not ready);
  *
  *  * there is no future chaining support for now (`.then().then()`);
@@ -283,6 +279,7 @@ class Future {
 public:
   Future() = default;
   explicit Future(std::shared_ptr<FutureState<T>> state) : state_(std::move(state)) {}
+  ~Future() = default;
 
   // Move type:
   Future(Future&) = delete;
@@ -327,17 +324,14 @@ public:
       throw std::future_error(std::future_errc::no_state);
     // Give shared-ownership to the continuation:
     auto state = std::move(state_);
-    state->set_continuation(simgrid::xbt::makeTask(
-      std::move(continuation), state));
+    state->set_continuation(simgrid::xbt::make_task(std::move(continuation), state));
   }
 
   /** Attach a continuation to this future
    *
    *  This version never does future unwrapping.
    */
-  template<class F>
-  auto thenNoUnwrap(F continuation)
-  -> Future<decltype(continuation(std::move(*this)))>
+  template <class F> auto then_no_unwrap(F continuation) -> Future<decltype(continuation(std::move(*this)))>
   {
     typedef decltype(continuation(std::move(*this))) R;
     if (state_ == nullptr)
@@ -347,16 +341,14 @@ public:
     Promise<R> promise;
     Future<R> future = promise.get_future();
     // ...and when the current future is ready...
-    state->set_continuation(simgrid::xbt::makeTask(
-      [](Promise<R> promise, std::shared_ptr<FutureState<T>> state, F continuation) {
-        // ...set the new future value by running the continuation.
-        Future<T> future(std::move(state));
-        simgrid::xbt::fulfillPromise(promise,[&]{
-          return continuation(std::move(future));
-        });
-      },
-      std::move(promise), state, std::move(continuation)));
-    return std::move(future);
+    state->set_continuation(simgrid::xbt::make_task(
+        [](Promise<R> promise, std::shared_ptr<FutureState<T>> state, F continuation) {
+          // ...set the new future value by running the continuation.
+          Future<T> future(std::move(state));
+          simgrid::xbt::fulfill_promise(promise, [&continuation, &future] { return continuation(std::move(future)); });
+        },
+        std::move(promise), state, std::move(continuation)));
+    return future;
   }
 
   /** Attach a continuation to this future
@@ -373,7 +365,7 @@ public:
   auto then(F continuation) -> typename std::enable_if<not is_future<decltype(continuation(std::move(*this)))>::value,
                                                        Future<decltype(continuation(std::move(*this)))>>::type
   {
-    return this->thenNoUnwrap(std::move(continuation));
+    return this->then_no_unwrap(std::move(continuation));
   }
 
   /** Attach a continuation to this future (future chaining) */
@@ -384,13 +376,13 @@ public:
        decltype(continuation(std::move(*this)))
      >::type
   {
-    return unwrapFuture(this->thenNoUnwap(std::move(continuation)));
+    return unwrap_future(this->then_no_unwrap(std::move(continuation)));
   }
 
   /** Get the value from the future
    *
    *  The future must be valid and ready in order to make this call.
-   *  @ref std::future blocks when the future is not ready but we are
+   *  std::future blocks when the future is not ready but we are
    *  completely single-threaded so blocking would be a deadlock.
    *  After the call, the future becomes invalid.
    *
@@ -410,13 +402,12 @@ private:
   std::shared_ptr<FutureState<T>> state_;
 };
 
-template<class T>
-Future<T> unwrapFuture(Future<Future<T>> future)
+template <class T> Future<T> unwrap_future(Future<Future<T>> future)
 {
   Promise<T> promise;
   Future<T> result = promise.get_future();
-  bindPromise(std::move(promise), std::move(future));
-  return std::move(result);
+  bind_promise(std::move(promise), std::move(future));
+  return result;
 }
 
 /** Producer side of a @ref simgrid::kernel::Future
@@ -424,14 +415,14 @@ Future<T> unwrapFuture(Future<Future<T>> future)
  *  A @ref Promise is connected to some `Future` and can be used to
  *  set its result.
  *
- *  Similar to @ref std::promise
+ *  Similar to std::promise
  *
  *  <code>
  *  // Create a promise and a future:
  *  auto promise = std::make_shared<simgrid::kernel::Promise<T>>();
  *  auto future = promise->get_future();
  *
- *  SIMIX_timer_set(date, [promise] {
+ *  simgrid::simix::Timer::set(date, [promise] {
  *    try {
  *      int value = compute_the_value();
  *      if (value < 0)
@@ -441,8 +432,8 @@ Future<T> unwrapFuture(Future<Future<T>> future)
  *      promise.set_value(value);
  *    }
  *    catch (...) {
- *      // If an error occured, we can set an exception which
- *      // will be throwed buy future.get():
+ *      // If an error occurred, we can set an exception which
+ *      // will be thrown by future.get():
  *      promise.set_exception(std::current_exception());
  *    }
  *  });
@@ -454,17 +445,13 @@ Future<T> unwrapFuture(Future<Future<T>> future)
 template<class T>
 class Promise {
 public:
-  explicit Promise() : state_(std::make_shared<FutureState<T>>()) {}
+  Promise() = default;
   explicit Promise(std::shared_ptr<FutureState<T>> state) : state_(std::move(state)) {}
 
   // Move type
   Promise(Promise const&) = delete;
   Promise& operator=(Promise const&) = delete;
-  Promise(Promise&& that) :
-    state_(std::move(that.state_)), future_get_(that.future_get_)
-  {
-    that.future_get_ = false;
-  }
+  Promise(Promise&& that) : state_(std::move(that.state_)) { std::swap(future_get_, that.future_get_); }
 
   Promise& operator=(Promise&& that)
   {
@@ -502,15 +489,15 @@ public:
   }
 
 private:
-  std::shared_ptr<FutureState<T>> state_;
+  std::shared_ptr<FutureState<T>> state_{new FutureState<T>()};
   bool future_get_ = false;
 };
 
 template<>
 class Promise<void> {
 public:
-  Promise() : state_(std::make_shared<FutureState<void>>()) {}
-  Promise(std::shared_ptr<FutureState<void>> state) : state_(std::move(state)) {}
+  Promise() = default;
+  explicit Promise(std::shared_ptr<FutureState<void>> state) : state_(std::move(state)) {}
   ~Promise()
   {
     if (state_ && state_->get_status() == FutureStatus::not_ready)
@@ -521,11 +508,7 @@ public:
   // Move type
   Promise(Promise const&) = delete;
   Promise& operator=(Promise const&) = delete;
-  Promise(Promise&& that) :
-    state_(std::move(that.state_)), future_get_(that.future_get_)
-  {
-    that.future_get_ = false;
-  }
+  Promise(Promise&& that) : state_(std::move(that.state_)) { std::swap(future_get_, that.future_get_); }
   Promise& operator=(Promise&& that)
   {
     this->state_ = std::move(that.state_);
@@ -557,7 +540,7 @@ public:
   }
 
 private:
-  std::shared_ptr<FutureState<void>> state_;
+  std::shared_ptr<FutureState<void>> state_{new FutureState<void>()};
   bool future_get_ = false;
 };