Commit 1d42dc0b authored by Hans Fugal's avatar Hans Fugal Committed by Tudor Bosman

(wangle) s/FutureObject/detail::State/

Summary:
codemod
I never was satisfied with this name. `State` feels a little better. More descriptive. But still pretty generic, so I'm open to alternative ideas.

Test Plan: It still builds and tests pass.

Reviewed By: hannesr@fb.com

Subscribers: jsedgwick, net-systems@, fugalh, exa

FB internal diff: D1411506
parent 02a9ec75
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
#pragma once #pragma once
#include "detail.h" #include "detail/State.h"
#include <folly/LifoSem.h> #include <folly/LifoSem.h>
namespace folly { namespace wangle { namespace folly { namespace wangle {
...@@ -32,26 +32,26 @@ struct isFuture<Future<T> > { ...@@ -32,26 +32,26 @@ struct isFuture<Future<T> > {
}; };
template <class T> template <class T>
Future<T>::Future(Future<T>&& other) noexcept : obj_(other.obj_) { Future<T>::Future(Future<T>&& other) noexcept : state_(other.state_) {
other.obj_ = nullptr; other.state_ = nullptr;
} }
template <class T> template <class T>
Future<T>& Future<T>::operator=(Future<T>&& other) { Future<T>& Future<T>::operator=(Future<T>&& other) {
std::swap(obj_, other.obj_); std::swap(state_, other.state_);
return *this; return *this;
} }
template <class T> template <class T>
Future<T>::~Future() { Future<T>::~Future() {
if (obj_) { if (state_) {
setCallback_([](Try<T>&&) {}); // detach setCallback_([](Try<T>&&) {}); // detach
} }
} }
template <class T> template <class T>
void Future<T>::throwIfInvalid() const { void Future<T>::throwIfInvalid() const {
if (!obj_) if (!state_)
throw NoState(); throw NoState();
} }
...@@ -59,8 +59,8 @@ template <class T> ...@@ -59,8 +59,8 @@ template <class T>
template <class F> template <class F>
void Future<T>::setCallback_(F&& func) { void Future<T>::setCallback_(F&& func) {
throwIfInvalid(); throwIfInvalid();
obj_->setCallback_(std::move(func)); state_->setCallback_(std::move(func));
obj_ = nullptr; state_ = nullptr;
} }
template <class T> template <class T>
...@@ -87,10 +87,10 @@ Future<T>::then(F&& func) { ...@@ -87,10 +87,10 @@ Future<T>::then(F&& func) {
sophisticated that avoids making a new Future object when it can, as an sophisticated that avoids making a new Future object when it can, as an
optimization. But this is correct. optimization. But this is correct.
obj_ can't be moved, it is explicitly disallowed (as is copying). But state_ can't be moved, it is explicitly disallowed (as is copying). But
if there's ever a reason to allow it, this is one place that makes that if there's ever a reason to allow it, this is one place that makes that
assumption and would need to be fixed. We use a standard shared pointer assumption and would need to be fixed. We use a standard shared pointer
for obj_ (by copying it in), which means in essence obj holds a shared for state_ (by copying it in), which means in essence obj holds a shared
pointer to itself. But this shouldn't leak because Promise will not pointer to itself. But this shouldn't leak because Promise will not
outlive the continuation, because Promise will setException() with a outlive the continuation, because Promise will setException() with a
broken Promise if it is destructed before completed. We could use a broken Promise if it is destructed before completed. We could use a
...@@ -102,11 +102,11 @@ Future<T>::then(F&& func) { ...@@ -102,11 +102,11 @@ Future<T>::then(F&& func) {
We have to move in the Promise and func using the MoveWrapper We have to move in the Promise and func using the MoveWrapper
hack. (func could be copied but it's a big drag on perf). hack. (func could be copied but it's a big drag on perf).
Two subtle but important points about this design. FutureObject has no Two subtle but important points about this design. detail::State has no
back pointers to Future or Promise, so if Future or Promise get moved back pointers to Future or Promise, so if Future or Promise get moved
(and they will be moved in performant code) we don't have to do (and they will be moved in performant code) we don't have to do
anything fancy. And because we store the continuation in the anything fancy. And because we store the continuation in the
FutureObject, not in the Future, we can execute the continuation even detail::State, not in the Future, we can execute the continuation even
after the Future has gone out of scope. This is an intentional design after the Future has gone out of scope. This is an intentional design
decision. It is likely we will want to be able to cancel a continuation decision. It is likely we will want to be able to cancel a continuation
in some circumstances, but I think it should be explicit not implicit in some circumstances, but I think it should be explicit not implicit
...@@ -164,21 +164,21 @@ template <class T> ...@@ -164,21 +164,21 @@ template <class T>
typename std::add_lvalue_reference<T>::type Future<T>::value() { typename std::add_lvalue_reference<T>::type Future<T>::value() {
throwIfInvalid(); throwIfInvalid();
return obj_->value(); return state_->value();
} }
template <class T> template <class T>
typename std::add_lvalue_reference<const T>::type Future<T>::value() const { typename std::add_lvalue_reference<const T>::type Future<T>::value() const {
throwIfInvalid(); throwIfInvalid();
return obj_->value(); return state_->value();
} }
template <class T> template <class T>
Try<T>& Future<T>::getTry() { Try<T>& Future<T>::getTry() {
throwIfInvalid(); throwIfInvalid();
return obj_->getTry(); return state_->getTry();
} }
template <class T> template <class T>
...@@ -191,7 +191,7 @@ inline Later<T> Future<T>::via(Executor* executor) { ...@@ -191,7 +191,7 @@ inline Later<T> Future<T>::via(Executor* executor) {
template <class T> template <class T>
bool Future<T>::isReady() const { bool Future<T>::isReady() const {
throwIfInvalid(); throwIfInvalid();
return obj_->ready(); return state_->ready();
} }
// makeFuture // makeFuture
......
...@@ -181,13 +181,13 @@ class Future { ...@@ -181,13 +181,13 @@ class Future {
void setCallback_(F&& func); void setCallback_(F&& func);
private: private:
typedef detail::FutureObject<T>* objPtr; typedef detail::State<T>* statePtr;
// shared state object // shared state object
objPtr obj_; statePtr state_;
explicit explicit
Future(objPtr obj) : obj_(obj) {} Future(statePtr obj) : state_(obj) {}
void throwIfInvalid() const; void throwIfInvalid() const;
......
...@@ -20,30 +20,30 @@ ...@@ -20,30 +20,30 @@
#include <thread> #include <thread>
#include "WangleException.h" #include "WangleException.h"
#include "detail.h" #include "detail/State.h"
namespace folly { namespace wangle { namespace folly { namespace wangle {
template <class T> template <class T>
Promise<T>::Promise() : retrieved_(false), obj_(new detail::FutureObject<T>()) Promise<T>::Promise() : retrieved_(false), state_(new detail::State<T>())
{} {}
template <class T> template <class T>
Promise<T>::Promise(Promise<T>&& other) : Promise<T>::Promise(Promise<T>&& other) :
retrieved_(other.retrieved_), obj_(other.obj_) { retrieved_(other.retrieved_), state_(other.state_) {
other.obj_ = nullptr; other.state_ = nullptr;
} }
template <class T> template <class T>
Promise<T>& Promise<T>::operator=(Promise<T>&& other) { Promise<T>& Promise<T>::operator=(Promise<T>&& other) {
std::swap(obj_, other.obj_); std::swap(state_, other.state_);
std::swap(retrieved_, other.retrieved_); std::swap(retrieved_, other.retrieved_);
return *this; return *this;
} }
template <class T> template <class T>
void Promise<T>::throwIfFulfilled() { void Promise<T>::throwIfFulfilled() {
if (!obj_) if (!state_)
throw PromiseAlreadySatisfied(); throw PromiseAlreadySatisfied();
} }
...@@ -55,7 +55,7 @@ void Promise<T>::throwIfRetrieved() { ...@@ -55,7 +55,7 @@ void Promise<T>::throwIfRetrieved() {
template <class T> template <class T>
Promise<T>::~Promise() { Promise<T>::~Promise() {
if (obj_) { if (state_) {
setException(BrokenPromise()); setException(BrokenPromise());
} }
} }
...@@ -65,7 +65,7 @@ Future<T> Promise<T>::getFuture() { ...@@ -65,7 +65,7 @@ Future<T> Promise<T>::getFuture() {
throwIfRetrieved(); throwIfRetrieved();
throwIfFulfilled(); throwIfFulfilled();
retrieved_ = true; retrieved_ = true;
return Future<T>(obj_); return Future<T>(state_);
} }
template <class T> template <class T>
...@@ -78,21 +78,21 @@ void Promise<T>::setException(E const& e) { ...@@ -78,21 +78,21 @@ void Promise<T>::setException(E const& e) {
template <class T> template <class T>
void Promise<T>::setException(std::exception_ptr const& e) { void Promise<T>::setException(std::exception_ptr const& e) {
throwIfFulfilled(); throwIfFulfilled();
obj_->setException(e); state_->setException(e);
if (!retrieved_) { if (!retrieved_) {
delete obj_; delete state_;
} }
obj_ = nullptr; state_ = nullptr;
} }
template <class T> template <class T>
void Promise<T>::fulfilTry(Try<T>&& t) { void Promise<T>::fulfilTry(Try<T>&& t) {
throwIfFulfilled(); throwIfFulfilled();
obj_->fulfil(std::move(t)); state_->fulfil(std::move(t));
if (!retrieved_) { if (!retrieved_) {
delete obj_; delete state_;
} }
obj_ = nullptr; state_ = nullptr;
} }
template <class T> template <class T>
...@@ -102,11 +102,11 @@ void Promise<T>::setValue(M&& v) { ...@@ -102,11 +102,11 @@ void Promise<T>::setValue(M&& v) {
"Use setValue() instead"); "Use setValue() instead");
throwIfFulfilled(); throwIfFulfilled();
obj_->fulfil(Try<T>(std::forward<M>(v))); state_->fulfil(Try<T>(std::forward<M>(v)));
if (!retrieved_) { if (!retrieved_) {
delete obj_; delete state_;
} }
obj_ = nullptr; state_ = nullptr;
} }
template <class T> template <class T>
...@@ -115,11 +115,11 @@ void Promise<T>::setValue() { ...@@ -115,11 +115,11 @@ void Promise<T>::setValue() {
"Use setValue(value) instead"); "Use setValue(value) instead");
throwIfFulfilled(); throwIfFulfilled();
obj_->fulfil(Try<void>()); state_->fulfil(Try<void>());
if (!retrieved_) { if (!retrieved_) {
delete obj_; delete state_;
} }
obj_ = nullptr; state_ = nullptr;
} }
template <class T> template <class T>
......
...@@ -76,13 +76,13 @@ public: ...@@ -76,13 +76,13 @@ public:
void fulfil(F&& func); void fulfil(F&& func);
private: private:
typedef typename Future<T>::objPtr objPtr; typedef typename Future<T>::statePtr statePtr;
// Whether the Future has been retrieved (a one-time operation). // Whether the Future has been retrieved (a one-time operation).
bool retrieved_; bool retrieved_;
// shared state object // shared state object
objPtr obj_; statePtr state_;
void throwIfFulfilled(); void throwIfFulfilled();
void throwIfRetrieved(); void throwIfRetrieved();
......
...@@ -17,29 +17,30 @@ ...@@ -17,29 +17,30 @@
#pragma once #pragma once
#include <atomic> #include <atomic>
#include <folly/Optional.h>
#include <stdexcept> #include <stdexcept>
#include <vector> #include <vector>
#include "Try.h" #include <folly/Optional.h>
#include "Promise.h"
#include "Future.h" #include <folly/wangle/Try.h>
#include <folly/wangle/Promise.h>
#include <folly/wangle/Future.h>
namespace folly { namespace wangle { namespace detail { namespace folly { namespace wangle { namespace detail {
/** The shared state object for Future and Promise. */ /** The shared state object for Future and Promise. */
template<typename T> template<typename T>
class FutureObject { class State {
public: public:
FutureObject() = default; State() = default;
// not copyable // not copyable
FutureObject(FutureObject const&) = delete; State(State const&) = delete;
FutureObject& operator=(FutureObject const&) = delete; State& operator=(State const&) = delete;
// not movable (see comment in the implementation of Future::then) // not movable (see comment in the implementation of Future::then)
FutureObject(FutureObject&&) noexcept = delete; State(State&&) noexcept = delete;
FutureObject& operator=(FutureObject&&) = delete; State& operator=(State&&) = delete;
Try<T>& getTry() { Try<T>& getTry() {
return *value_; return *value_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment