X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/e44a0d71a8bacd7ab03e284fc32ad23731f5869c..c6bbeb1829c36ff45b43ab25f9d8d3f53f554d98:/include/simgrid/kernel/future.hpp diff --git a/include/simgrid/kernel/future.hpp b/include/simgrid/kernel/future.hpp index 581db40333..c55f741d95 100644 --- a/include/simgrid/kernel/future.hpp +++ b/include/simgrid/kernel/future.hpp @@ -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&& job); + XBT_PUBLIC void schedule(simgrid::xbt::Task&& 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 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(); - 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 -void bindPromise(Promise promise, Future future) +template void bind_promise(Promise&& promise, Future future) { - struct PromiseBinder { + class PromiseBinder { public: - explicit PromiseBinder(Promise promise) : promise_(std::move(promise)) {} - void operator()(Future future) - { - simgrid::xbt::setPromise(promise_, future); - } + explicit PromiseBinder(Promise&& promise) : promise_(std::move(promise)) {} + void operator()(Future future) { simgrid::xbt::set_promise(promise_, future); } + private: Promise promise_; }; future.then_(PromiseBinder(std::move(promise))); } -template Future unwrapFuture(Future> future); +template Future unwrap_future(Future> 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 Future unwrapFuture(Future> 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 Future unwrapFuture(Future> future); * ); * * - * 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 Future unwrapFuture(Future> 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> 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 - auto thenNoUnwrap(F continuation) - -> Future + template auto then_no_unwrap(F continuation) -> Future { typedef decltype(continuation(std::move(*this))) R; if (state_ == nullptr) @@ -347,16 +341,14 @@ public: Promise promise; Future future = promise.get_future(); // ...and when the current future is ready... - state->set_continuation(simgrid::xbt::makeTask( - [](Promise promise, std::shared_ptr> state, F continuation) { - // ...set the new future value by running the continuation. - Future 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 promise, std::shared_ptr> state, F continuation) { + // ...set the new future value by running the continuation. + Future 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::value, Future>::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> state_; }; -template -Future unwrapFuture(Future> future) +template Future unwrap_future(Future> future) { Promise promise; Future 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 unwrapFuture(Future> 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 * * * // Create a promise and a future: * auto promise = std::make_shared>(); * 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 unwrapFuture(Future> 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 unwrapFuture(Future> future) template class Promise { public: - explicit Promise() : state_(std::make_shared>()) {} + Promise() = default; explicit Promise(std::shared_ptr> 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> state_; + std::shared_ptr> state_{new FutureState()}; bool future_get_ = false; }; template<> class Promise { public: - Promise() : state_(std::make_shared>()) {} - Promise(std::shared_ptr> state) : state_(std::move(state)) {} + Promise() = default; + explicit Promise(std::shared_ptr> 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> state_; + std::shared_ptr> state_{new FutureState()}; bool future_get_ = false; };