Simulant  21.09-46
A portable game engine for Windows, OSX, Linux, Dreamcast, and PSP
helpers.h
1 #pragma once
2 
3 #include <functional>
4 #include <memory>
5 #include <type_traits>
6 
7 #include "../generic/static_if.h"
8 #include "coroutine.h"
9 #include "../threads/thread.h"
10 
11 namespace smlt {
12 
13 namespace promise_impl {
14 
15 template<typename T>
16 struct PromiseState {
17  typedef std::shared_ptr<PromiseState<T>> ptr;
18 
19  optional<T> value;
20 };
21 
22 template<>
23 struct PromiseState<void> {
24  typedef std::shared_ptr<PromiseState<void>> ptr;
25  bool value;
26 };
27 
28 
29 template<typename Func, typename T>
31 public:
32  void operator()(Func f, typename PromiseState<T>::ptr state) {
33  state->value = f();
34  }
35 };
36 
37 template<typename Func>
38 struct CallAndSetState<Func, void> {
39 public:
40  void operator()(Func f, typename PromiseState<void>::ptr state) {
41  f();
42  state->value = true;
43  }
44 };
45 
46 }
47 
48 template<typename T>
49 class CRPromise {
50 public:
51  bool is_ready() const {
52  return state_ && state_->value;
53  }
54 
55  T& value() const {
56  assert(state_->value);
57  return (state_->value.value());
58  }
59 
60  /* Starts another coroutine that waits until
61  * this one has been fulfilled */
62  template<typename Func>
63  CRPromise<typename std::result_of<Func()>::type> then(Func func);
64 
65 private:
66  template<typename Func>
67  friend CRPromise<typename std::result_of<Func()>::type> cr_async(Func func);
68 
69  CRPromise(typename promise_impl::PromiseState<T>::ptr state):
70  state_(state) {
71 
72  }
73 
74  typename promise_impl::PromiseState<T>::ptr state_;
75 };
76 
77 template<>
78 class CRPromise<void> {
79 private:
80  template<typename Func>
81  friend CRPromise<typename std::result_of<Func()>::type> cr_async(Func func);
82 
83  CRPromise(typename promise_impl::PromiseState<void>::ptr state):
84  state_(state) {
85 
86  }
87 
88  typename promise_impl::PromiseState<void>::ptr state_;
89 
90 public:
91  bool is_ready() const {
92  return state_ && state_->value;
93  }
94 
95  void value() const {}
96 
97  /* Starts another coroutine that waits until
98  * this one has been fulfilled */
99  template<typename Func>
100  CRPromise<typename std::result_of<Func()>::type> then(Func func);
101 };
102 
103 void _trigger_coroutine(std::function<void ()> func);
104 void _trigger_idle_updates();
105 
106 template<typename Func>
107 CRPromise<typename std::result_of<Func()>::type> cr_async(Func func) {
108  typedef typename std::result_of<Func()>::type T;
109 
110  auto state = std::make_shared<typename promise_impl::PromiseState<T>>();
111  CRPromise<T> promise(state);
112 
113  _trigger_coroutine([state, func]() {
115  });
116 
117  return promise;
118 }
119 
120 void cr_yield();
121 
122 
123 /* Starts another coroutine that waits until
124  * this one has been fulfilled */
125 
126 template<typename T>
127 template<typename Func>
128 CRPromise<typename std::result_of<Func()>::type> CRPromise<T>::then(Func func) {
129 
130  /* Copy the smart pointer and pass to the callback */
131  auto state = state_;
132 
133  auto cb = [this, func, state]() -> typename std::result_of<Func()>::type {
134  while(!state->value) {
135  cr_yield();
136  }
137 
138  return func();
139  };
140 
141  return cr_async(cb);
142 }
143 
144 template<typename Func>
145 CRPromise<typename std::result_of<Func()>::type> CRPromise<void>::then(Func func) {
146  auto state = state_;
147 
148  auto cb = [this, func, state]() -> typename std::result_of<Func()>::type {
149  while(!state->value) {
150  cr_yield();
151  }
152 
153  return func();
154  };
155 
156  return cr_async(cb);
157 }
158 
159 /* Will wait for the promise returned by a coroutine
160  * to be fulfilled. Be careful when calling from the main
161  * thread, because in this case only idle tasks and
162  * coroutines will be updated (no rendering or scene
163  * updates will happen while you are waiting).
164  *
165  * In the main thread you may prefer to use
166  * start_coroutine(...).then(...)
167  */
168 template<typename T>
169 T cr_await(const CRPromise<T>& promise) {
170  while(!promise.is_ready()) {
171  if(cort::within_coroutine()){
172  cr_yield();
173  } else {
174  _trigger_idle_updates();
175  thread::sleep(0);
176  }
177  }
178 
179  return promise.value();
180 }
181 
182 }
smlt::promise_impl::CallAndSetState
Definition: helpers.h:30
smlt
Definition: animation.cpp:25
smlt::CRPromise
Definition: helpers.h:49
smlt::optional
Definition: optional.h:13
smlt::promise_impl::PromiseState
Definition: helpers.h:16