Promise.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. /*
  2. * Copyright 2014-present Facebook, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #pragma once
  17. #include <functional>
  18. #include <folly/Portability.h>
  19. #include <folly/Try.h>
  20. #include <folly/futures/detail/Core.h>
  21. #include <folly/lang/Exception.h>
  22. namespace folly {
  23. class FOLLY_EXPORT PromiseException : public std::logic_error {
  24. public:
  25. using std::logic_error::logic_error;
  26. };
  27. class FOLLY_EXPORT PromiseInvalid : public PromiseException {
  28. public:
  29. PromiseInvalid() : PromiseException("Promise invalid") {}
  30. };
  31. class FOLLY_EXPORT PromiseAlreadySatisfied : public PromiseException {
  32. public:
  33. PromiseAlreadySatisfied() : PromiseException("Promise already satisfied") {}
  34. };
  35. class FOLLY_EXPORT FutureAlreadyRetrieved : public PromiseException {
  36. public:
  37. FutureAlreadyRetrieved() : PromiseException("Future already retrieved") {}
  38. };
  39. class FOLLY_EXPORT BrokenPromise : public PromiseException {
  40. public:
  41. explicit BrokenPromise(const std::string& type)
  42. : PromiseException("Broken promise for type name `" + type + '`') {}
  43. explicit BrokenPromise(const char* type) : BrokenPromise(std::string(type)) {}
  44. };
  45. // forward declaration
  46. template <class T>
  47. class SemiFuture;
  48. template <class T>
  49. class Future;
  50. namespace futures {
  51. namespace detail {
  52. template <class T>
  53. class FutureBase;
  54. struct EmptyConstruct {};
  55. template <typename T, typename F>
  56. class CoreCallbackState;
  57. } // namespace detail
  58. } // namespace futures
  59. /// Promises and futures provide a potentially nonblocking mechanism
  60. /// to execute a producer/consumer operation concurrently, with
  61. /// threading/pools controlled via an executor. There are multiple potential
  62. /// patterns for using promises and futures including some that block the
  63. /// caller, though that is discouraged; it should be used only when necessary.
  64. ///
  65. /// One typical pattern uses a series of calls to set up a small, limited
  66. /// program that...
  67. ///
  68. /// - ...performs the desired operations (based on a lambda)...
  69. /// - ...on an asynchronously provided input (an exception or a value)...
  70. /// - ...lazily, when that input is ready (without blocking the caller)...
  71. /// - ...using appropriate execution resources (determined by the executor)...
  72. /// - ...then after constructing the 'program,' launches the asynchronous
  73. /// producer.
  74. ///
  75. /// That usage pattern looks roughly like this:
  76. ///
  77. /// auto [p, f] = makePromiseContract(executor);
  78. /// g = std::move(f).then([](MyValue&& x) {
  79. /// ...executor runs this code if/when a MyValue is ready...
  80. /// });
  81. /// ...launch the async producer that eventually calls p.setResult()...
  82. ///
  83. /// This is just one of many potential usage patterns. It has the desired
  84. /// property of being nonblocking to the caller. Of course the `.then()`
  85. /// code is deferred until the produced value (or exception) is ready,
  86. /// but no code actually blocks pending completion of other operations.
  87. ///
  88. /// The promise/future mechanism is limited to a single object of some arbitrary
  89. /// type. It also supports a (logically) void result, i.e., in cases where the
  90. /// continuation/consumer (the `.then()` code if using the above pattern) is not
  91. /// expecting a value because the 'producer' is running for its side-effects.
  92. ///
  93. /// The primary data movement is from producer to consumer, however Promise and
  94. /// Future also provide a mechanism where the consumer can send an interruption
  95. /// message to the producer. The meaning and response to that interruption
  96. /// message is controlled by the promise; see `Promise::setInterruptHandler()`.
  97. ///
  98. /// Neither Promise nor Future is thread-safe. All internal interactions
  99. /// between a promise and its associated future are thread-safe, provided that
  100. /// callers otherwise honor the promise's contract and the future's contract.
  101. ///
  102. /// Logically there are up to three threads (though in practice there are often
  103. /// fewer - one thread might take on more than one role):
  104. ///
  105. /// - Set-up thread: thread used to construct the Promise, and often also to
  106. /// set up the SemiFuture/Future.
  107. /// - Producer thread: thread that produces the result.
  108. /// - Consumer thread: thread in which the continuation is invoked (a
  109. /// continuation is a callback provided to `.then` or to a variant).
  110. ///
  111. /// For description purposes, the term 'shared state' is used to describe the
  112. /// logical state shared by the promise and the future. This 'third object'
  113. /// represents things like whether the result has been fulfilled, the value or
  114. /// exception in that result, and the data needed to handle interruption
  115. /// requests.
  116. ///
  117. /// A promise can be in various logical states:
  118. ///
  119. /// - valid vs. invalid (has vs. does not have a shared state, respectfully).
  120. /// - fulfilled vs. unfulfilled (an invalid promise is always fulfilled; a valid
  121. /// promise is fulfilled if the shared-state has a result).
  122. ///
  123. /// A promise `p` may optionally have an associated future. This future, if it
  124. /// exists, may be either a SemiFuture or a Future, and is defined as the
  125. /// future (if any) that holds the same shared state as promise `p`.
  126. /// The associated future is initially the future returned from
  127. /// `p.getFuture()` or `p.getSemiFuture()`, but various operations
  128. /// may transfer the shared state from one future to another.
  129. template <class T>
  130. class Promise {
  131. public:
  132. /// Returns an invalid promise.
  133. ///
  134. /// Postconditions:
  135. ///
  136. /// - `RESULT.valid() == false`
  137. /// - `RESULT.isFulfilled() == true`
  138. static Promise<T> makeEmpty() noexcept;
  139. /// Constructs a valid but unfulfilled promise.
  140. ///
  141. /// Postconditions:
  142. ///
  143. /// - `valid() == true` (it will have a shared state)
  144. /// - `isFulfilled() == false` (its shared state won't have a result)
  145. Promise();
  146. /// Postconditions:
  147. ///
  148. /// - If `valid()` and `!isFulfilled()`, the associated future (if any) will
  149. /// be completed with a `BrokenPromise` exception *as if* by
  150. /// `setException(...)`.
  151. /// - If `valid()`, releases, possibly destroying, the shared state.
  152. ~Promise();
  153. // not copyable
  154. Promise(Promise const&) = delete;
  155. Promise& operator=(Promise const&) = delete;
  156. /// Move ctor
  157. ///
  158. /// Postconditions:
  159. ///
  160. /// - `this` will have whatever shared-state was previously held by `other`
  161. /// (if any)
  162. /// - `other.valid()` will be false (`other` will not have any shared state)
  163. Promise(Promise<T>&& other) noexcept;
  164. /// Move assignment
  165. ///
  166. /// Postconditions:
  167. ///
  168. /// - If `valid()` and `!isFulfilled()`, the associated future (if any) will
  169. /// be completed with a `BrokenPromise` exception *as if* by
  170. /// `setException(...)`.
  171. /// - If `valid()`, releases, possibly destroying, the original shared state.
  172. /// - `this` will have whatever shared-state was previously held by `other`
  173. /// (if any)
  174. /// - `other.valid()` will be false (`other` will not have any shared state)
  175. Promise& operator=(Promise<T>&& other) noexcept;
  176. /// Return a SemiFuture associated with this Promise, sharing the same shared
  177. /// state as `this`.
  178. ///
  179. /// Preconditions:
  180. ///
  181. /// - `valid() == true` (else throws PromiseInvalid)
  182. /// - neither getSemiFuture() nor getFuture() may have been called previously
  183. /// on `this` Promise (else throws FutureAlreadyRetrieved)
  184. ///
  185. /// Postconditions:
  186. ///
  187. /// - `RESULT.valid() == true`
  188. /// - RESULT will share the same shared-state as `this`
  189. ///
  190. /// DEPRECATED: use `folly::makePromiseContract()` instead.
  191. SemiFuture<T> getSemiFuture();
  192. /// Return a Future associated with this Promise, sharing the same shared
  193. /// state as `this`.
  194. ///
  195. /// Preconditions:
  196. ///
  197. /// - `valid() == true` (else throws PromiseInvalid)
  198. /// - neither getSemiFuture() nor getFuture() may have been called previously
  199. /// on `this` Promise (else throws FutureAlreadyRetrieved)
  200. ///
  201. /// Postconditions:
  202. ///
  203. /// - `RESULT.valid() == true`
  204. /// - RESULT will share the same shared-state as `this`
  205. ///
  206. /// DEPRECATED: use `folly::makePromiseContract()` instead. If you can't use
  207. /// that, use `this->getSemiFuture()` then get a Future by calling `.via()`
  208. /// with an appropriate executor.
  209. Future<T> getFuture();
  210. /// Fulfill the Promise with an exception_wrapper.
  211. ///
  212. /// Sample usage:
  213. ///
  214. /// Promise<MyValue> p = ...
  215. /// ...
  216. /// auto const ep = std::exception_ptr();
  217. /// auto const ew = exception_wrapper::from_exception_ptr(ep);
  218. /// p.setException(ew);
  219. ///
  220. /// Functionally equivalent to `setTry(Try<T>(std::move(ew)))`
  221. ///
  222. /// Preconditions:
  223. ///
  224. /// - `valid() == true` (else throws PromiseInvalid)
  225. /// - `isFulfilled() == false` (else throws PromiseAlreadySatisfied)
  226. ///
  227. /// Postconditions:
  228. ///
  229. /// - `isFulfilled() == true`
  230. /// - `valid() == true` (unchanged)
  231. /// - The associated future (if any) will complete with the exception.
  232. void setException(exception_wrapper ew);
  233. /// Fulfill the Promise with exception `e` *as if* by
  234. /// `setException(make_exception_wrapper<E>(e))`.
  235. ///
  236. /// Please see `setException(exception_wrapper)` for semantics/contract.
  237. template <class E>
  238. typename std::enable_if<std::is_base_of<std::exception, E>::value>::type
  239. setException(E const& e);
  240. /// Sets a handler for the producer to receive a (logical) interruption
  241. /// request (exception) sent from the consumer via `future.raise()`.
  242. ///
  243. /// Details: The consumer calls `future.raise()` when it wishes to send a
  244. /// logical interruption message (an exception), and that exception/message
  245. /// is passed to `fn()`. The thread used to call `fn()` depends on timing
  246. /// (see Postconditions for threading details).
  247. ///
  248. /// Handler `fn()` can do anything you want, but if you bother to set one
  249. /// then you probably will want to (more or less immediately) fulfill the
  250. /// promise with an exception (or other special value) indicating how the
  251. /// interrupt was handled.
  252. ///
  253. /// This call silently does nothing if `isFulfilled()`.
  254. ///
  255. /// Preconditions:
  256. ///
  257. /// - `valid() == true` (else throws PromiseInvalid)
  258. /// - `fn` must be copyable and must be invocable with
  259. /// `exception_wrapper const&`
  260. /// - the code within `fn()` must be safe to run either synchronously within
  261. /// the `setInterruptHandler()` call or asynchronously within the consumer
  262. /// thread's call to `future.raise()`.
  263. /// - the code within `fn()` must also be safe to run after this promise is
  264. /// fulfilled; this may have lifetime/race-case ramifications, e.g., if the
  265. /// code of `fn()` might access producer-resources that will be destroyed,
  266. /// then the destruction of those producer-resources must be deferred beyond
  267. /// the moment when this promise is fulfilled.
  268. ///
  269. /// Postconditions:
  270. ///
  271. /// - if the consumer calls `future.raise()` early enough (up to a particular
  272. /// moment within the `setInterruptHandler()` call), `fn()` will be called
  273. /// synchronously (in the current thread, during this call).
  274. /// - if the consumer calls `future.raise()` after that moment within
  275. /// `setInterruptHandler()` but before this promise is fulfilled, `fn()`
  276. /// will be called asynchronously (in the consumer's thread, within the call
  277. /// to `future.raise()`).
  278. /// - if the consumer calls `future.raise()` after this promise is fulfilled,
  279. /// `fn()` may or may not be called at all, and if it is called, it will be
  280. /// called asynchronously (within the consumer's call to `future.raise()`).
  281. ///
  282. /// IMPORTANT: `fn()` should return quickly since it could block this call
  283. /// to `promise.setInterruptHandler()` and/or a concurrent call to
  284. /// `future.raise()`. Those two functions contend on the same lock; those
  285. /// calls could block if `fn()` is invoked within one of those while the
  286. /// lock is held.
  287. template <typename F>
  288. void setInterruptHandler(F&& fn);
  289. /// Fulfills a (logically) void Promise, that is, Promise<Unit>.
  290. /// (If you want a void-promise, use Promise<Unit>, not Promise<void>.)
  291. ///
  292. /// Preconditions:
  293. ///
  294. /// - `valid() == true` (else throws PromiseInvalid)
  295. /// - `isFulfilled() == false` (else throws PromiseAlreadySatisfied)
  296. ///
  297. /// Postconditions:
  298. ///
  299. /// - `isFulfilled() == true`
  300. /// - `valid() == true` (unchanged)
  301. template <class B = T>
  302. typename std::enable_if<std::is_same<Unit, B>::value, void>::type setValue() {
  303. setTry(Try<T>(T()));
  304. }
  305. /// Fulfill the Promise with the specified value using perfect forwarding.
  306. ///
  307. /// Functionally equivalent to `setTry(Try<T>(std::forward<M>(value)))`
  308. ///
  309. /// Preconditions:
  310. ///
  311. /// - `valid() == true` (else throws PromiseInvalid)
  312. /// - `isFulfilled() == false` (else throws PromiseAlreadySatisfied)
  313. ///
  314. /// Postconditions:
  315. ///
  316. /// - `isFulfilled() == true`
  317. /// - `valid() == true` (unchanged)
  318. /// - The associated future will see the value, e.g., in its continuation.
  319. template <class M>
  320. void setValue(M&& value);
  321. /// Fulfill the Promise with the specified Try (value or exception).
  322. ///
  323. /// Preconditions:
  324. ///
  325. /// - `valid() == true` (else throws PromiseInvalid)
  326. /// - `isFulfilled() == false` (else throws PromiseAlreadySatisfied)
  327. ///
  328. /// Postconditions:
  329. ///
  330. /// - `isFulfilled() == true`
  331. /// - `valid() == true` (unchanged)
  332. /// - The associated future will see the result, e.g., in its continuation.
  333. void setTry(Try<T>&& t);
  334. /// Fulfill this Promise with the result of a function that takes no
  335. /// arguments and returns something implicitly convertible to T.
  336. ///
  337. /// Example:
  338. ///
  339. /// p.setWith([] { do something that may throw; return a T; });
  340. ///
  341. /// Functionally equivalent to `setTry(makeTryWith(static_cast<F&&>(func)));`
  342. ///
  343. /// Preconditions:
  344. ///
  345. /// - `valid() == true` (else throws PromiseInvalid)
  346. /// - `isFulfilled() == false` (else throws PromiseAlreadySatisfied)
  347. ///
  348. /// Postconditions:
  349. ///
  350. /// - `func()` will be run synchronously (in this thread, during this call)
  351. /// - If `func()` returns, the return value will be captured as if via
  352. /// `setValue()`
  353. /// - If `func()` throws, the exception will be captured as if via
  354. /// `setException()`
  355. /// - `isFulfilled() == true`
  356. /// - `valid() == true` (unchanged)
  357. /// - The associated future will see the result, e.g., in its continuation.
  358. template <class F>
  359. void setWith(F&& func);
  360. /// true if this has a shared state;
  361. /// false if this has been consumed/moved-out.
  362. bool valid() const noexcept {
  363. return core_ != nullptr;
  364. }
  365. /// True if either this promise was fulfilled or is invalid.
  366. ///
  367. /// - True if `!valid()`
  368. /// - True if `valid()` and this was fulfilled (a prior call to `setValue()`,
  369. /// `setTry()`, `setException()`, or `setWith()`)
  370. bool isFulfilled() const noexcept;
  371. private:
  372. template <class>
  373. friend class futures::detail::FutureBase;
  374. template <class>
  375. friend class SemiFuture;
  376. template <class>
  377. friend class Future;
  378. template <class, class>
  379. friend class futures::detail::CoreCallbackState;
  380. // Whether the Future has been retrieved (a one-time operation).
  381. bool retrieved_;
  382. using Core = futures::detail::Core<T>;
  383. // Throws PromiseInvalid if there is no shared state object; else returns it
  384. // by ref.
  385. //
  386. // Implementation methods should usually use this instead of `this->core_`.
  387. // The latter should be used only when you need the possibly-null pointer.
  388. Core& getCore() {
  389. return getCoreImpl(core_);
  390. }
  391. Core const& getCore() const {
  392. return getCoreImpl(core_);
  393. }
  394. template <typename CoreT>
  395. static CoreT& getCoreImpl(CoreT* core) {
  396. if (!core) {
  397. throw_exception<PromiseInvalid>();
  398. }
  399. return *core;
  400. }
  401. // shared core state object
  402. // usually you should use `getCore()` instead of directly accessing `core_`.
  403. Core* core_;
  404. explicit Promise(futures::detail::EmptyConstruct) noexcept;
  405. void throwIfFulfilled() const;
  406. void detach();
  407. };
  408. } // namespace folly
  409. #include <folly/futures/Future.h>
  410. #include <folly/futures/Promise-inl.h>