Honeycomb  0.1
Component-Model Framework
Future.h
Go to the documentation of this file.
1 // Honeycomb, Copyright (C) 2015 NewGamePlus Inc. Distributed under the Boost Software License v1.0.
2 #pragma once
3 
6 
7 namespace honey
8 {
9 
10 namespace future
11 {
12  enum class Status
13  {
14  ready,
15  timeout
16  };
17 }
18 
21 {
22 public:
23  typedef future::priv::StateBase StateBase;
24 
26  bool valid() const { return stateBase(); }
28  bool ready() const { auto state = stateBase(); if (!state) throw_ future::NoState(); return state->ready; }
29 
31  void wait() const { wait(MonoClock::TimePoint::max()); }
33  template<class Rep, class Period>
34  future::Status wait(Duration<Rep,Period> time) const { return wait(time == time.max() ? MonoClock::TimePoint::max() : MonoClock::now() + time); }
36  template<class Clock, class Dur>
38  {
39  auto state = stateBase();
40  if (!state) throw_ future::NoState();
41  ConditionLock::Scoped _(state->waiters);
42  while (!state->ready) if (!state->waiters.wait(time)) return future::Status::timeout;
43  return future::Status::ready;
44  }
45 
47  StateBase& __stateBase() const { assert(stateBase()); return *stateBase(); }
48 
49 protected:
50  virtual StateBase* stateBase() const = 0;
51 };
52 
53 template<class R> class Future;
54 template<class R> class SharedFuture;
55 
57 namespace future { namespace priv
58 {
59  template<class R> struct wrappedResult { typedef mt::tag<0> type; }; //dummy
60  template<class R> struct wrappedResult<Future<R>> { typedef R type; };
61 
62  template<class R> struct unwrapOnReady;
63 
64  template<class R> struct unwrapOnReady<Future<R>> : mt::FuncptrBase, SmallAllocatorObject
65  {
66  unwrapOnReady(Promise<R>&& promise) : promise(move(promise)) {}
67  void operator()(StateBase& src)
68  {
69  if (src.ready) src.ex ? promise.setException(src.ex) : promise.setValue(move(static_cast<State<R>&>(src).result()));
70  delete_(this);
71  }
72  Promise<R> promise;
73  };
74 
75  template<> struct unwrapOnReady<Future<void>> : mt::FuncptrBase, SmallAllocatorObject
76  {
77  unwrapOnReady(Promise<void>&& promise) : promise(move(promise)) {}
78  void operator()(StateBase& src)
79  {
80  if (src.ready) src.ex ? promise.setException(src.ex) : promise.setValue();
81  delete_(this);
82  }
83  Promise<void> promise;
84  };
85 } }
88 template<class Subclass, class R>
91 {
92 public:
94  template<class Sched, class Func>
96  then(Sched&& sched, Func&& f);
97  template<class Func>
99  then(Func&& f);
100 
102 
106  template< class R2 = typename future::priv::wrappedResult<R>::type,
107  typename std::enable_if<mt::True<R2>::value && std::is_base_of<FutureBase, R>::value, int>::type=0>
109  {
110  using namespace future::priv;
111  if (!subc()._state) throw_ future::NoState();
112  Promise<R2> promise{SmallAllocator<int>()};
113  auto future = promise.future();
114 
115  struct onReady : mt::FuncptrBase, SmallAllocatorObject
116  {
117  onReady(Promise<R2>&& promise) : promise(move(promise)) {}
118  void operator()(StateBase& src)
119  {
120  if (src.ready)
121  {
122  if (src.ex)
123  this->promise.setException(src.ex);
124  else
125  {
126  auto& wrapped = static_cast<State<R>&>(src).result();
127  wrapped._state->addOnReady(*new future::priv::unwrapOnReady<R>(move(this->promise)));
128  }
129  }
130  delete_(this);
131  }
132  Promise<R2> promise;
133  };
134 
135  subc()._state->addOnReady(*new onReady(move(promise)));
136  return future;
137  }
138 
139 private:
141  const Subclass& subc() const { return static_cast<const Subclass&>(*this); }
142  Subclass& subc() { return static_cast<Subclass&>(*this); }
143 };
144 
146 template<class R>
147 class Future : public FutureBase, public FutureCommon<Future<R>, R>
148 {
149  template<class> friend class Promise;
150  template<class, class> friend class FutureCommon;
151  template<class> friend class Future;
152  template<class> friend class SharedFuture;
153 
154 public:
155  typedef R Result;
156  typedef future::priv::State<R> State;
157 
158  Future() : _state(nullptr) {}
159  Future(Future&& rhs) noexcept : _state(nullptr) { operator=(move(rhs)); }
160 
161  Future& operator=(Future&& rhs) { _state = move(rhs._state); return *this; }
162 
164  SharedFuture<R> share() { return SharedFuture<R>(move(*this)); }
165 
167 
170  R get();
171 
173  State& __state() const { assert(_state); return *_state; }
174 
175 protected:
176  virtual StateBase* stateBase() const { return _state; }
177 
178 private:
179  explicit Future(const SharedPtr<State>& state) : _state(state) {}
180 
181  template<class R_>
182  struct getResult { static R_&& func(const SharedPtr<State>& state) { return move(state->result()); } };
183  template<class R_>
184  struct getResult<R_&> { static R_& func(const SharedPtr<State>& state) { return state->result(); } };
185 
186  SharedPtr<State> _state;
187 };
188 
189 template<class R>
191 {
192  wait();
193  R res = getResult<R>::func(_state);
194  auto ex = _state->ex;
195  _state = nullptr;
196  if (ex) ex->raise();
197  return res;
198 }
199 
200 template<>
201 inline void Future<void>::get()
202 {
203  wait();
204  auto ex = _state->ex;
205  _state = nullptr;
206  if (ex) ex->raise();
207 }
208 
210 template<class T, class R = typename std::decay<T>::type>
212 {
213  Promise<R> promise;
214  promise.setValue(forward<T>(val));
215  return promise.future();
216 }
217 
219 {
220  Promise<void> promise;
221  promise.setValue();
222  return promise.future();
223 }
224 
225 }
A scoped lock that references any lockable. Locks on construction and unlocks on destruction.
Definition: Mutex.h:10
R get()
Get the future result, waiting if necessary. Throws any exception stored in the result.
Definition: Future.h:190
TimePoint represented by a duration since a clock's epoch time.
Definition: TimePoint.h:11
virtual StateBase * stateBase() const
Definition: Future.h:176
static TimePoint now()
Get current time.
Definition: Clock.h:48
Future< typename std::result_of< Func(Subclass)>::type > then(Sched &&sched, Func &&f)
Append a continuation function that will be called when this future is ready. The ready future is pas...
future::Status wait(TimePoint< Clock, Dur > time) const
Wait until result is ready or until a certain time.
Definition: Future.h:37
Unique future, guarantees sole access to a future function result.
Definition: Future.h:53
bool valid() const
Check if this instance has state and can be used. State can be transferred out to another instance th...
Definition: Future.h:26
future::priv::State< R > State
Definition: Future.h:156
Inherit to declare that class is not copyable.
Definition: Meta.h:286
Shared future, allows multiple access to a future function result.
Definition: Future.h:54
void delete_(T *&p)
Destruct object, free memory and set pointer to null.
Definition: Allocator.h:75
State & __state() const
Get the shared state.
Definition: Future.h:173
Future< R2 > unwrap()
For wrapped futures Future>, returns a proxy Future that will be ready when the inner fu...
Definition: Future.h:108
the future result is ready
Future< R > future()
Get future from which delayed result can be retrieved.
Definition: Promise.h:207
Container to hold a delayed function result.
Definition: Promise.h:181
AllocatorObject< SmallAllocator > SmallAllocatorObject
Inherit from this class to use the small block allocator.
Definition: SmallAllocator.h:34
static auto _
Definition: Module.cpp:8
Future()
Definition: Future.h:158
mt::disable_if< mt::True< T >::value &&(mt::isRef< R >::value||std::is_void< R >::value)>::type setValue(T &&val)
Set stored result. Result is copy/move constructed from value.
Definition: Promise.h:223
Mixin for common future methods.
Definition: Future.h:90
SharedFuture< R > share()
Share the future between multiple future objects. This future is rendered invalid.
Definition: Future.h:164
bool ready() const
Check if result is ready.
Definition: Future.h:28
Objects that inherit from this class will use Alloc for new/delete ops.
Definition: Allocator.h:129
#define assert(...)
Forwards to assert_#args. See assert_1(), assert_2().
Definition: Debug.h:24
Future & operator=(Future &&rhs)
Definition: Future.h:161
Future< R > FutureCreate(T &&val)
Create a future that is immediately ready with the value.
Definition: Future.h:211
static constexpr Duration max()
Maximum duration (positive reps)
Definition: Duration.h:86
Status
Definition: Future.h:12
Duration represented by repetitions of a period. The period must be a ratio.
Definition: Duration.h:7
Use to differentiate an overloaded function by type. Accepts dummy parameter default value: func(tag<...
Definition: Meta.h:39
#define throw_
Use in place of throw keyword to throw a honey::Exception object polymorphically and provide debug in...
Definition: Exception.h:11
R Result
Definition: Future.h:155
Future(Future &&rhs) noexcept
Definition: Future.h:159
future::priv::StateBase StateBase
Definition: Future.h:23
Global allocator for small memory blocks. To provide a custom pool define SmallAllocator_createSingle...
Definition: SmallAllocator.h:23
void wait() const
Wait until result is ready.
Definition: Future.h:31
Definition: Promise.h:17
future::Status wait(Duration< Rep, Period > time) const
Wait until result is ready or until an amount of time has passed.
Definition: Future.h:34
StateBase & __stateBase() const
Get the shared state.
Definition: Future.h:47
Base class for Future types.
Definition: Future.h:20
Inherit to enable non-virtual functor calling.
Definition: Meta.h:231
Global Honeycomb namespace.
virtual StateBase * stateBase() const =0