Make some AsyncTest methods virtual to allow mocking them using gtest/gmock
[folly.git] / folly / futures / FutureSplitter.h
1 /*
2  * Copyright 2017 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
17 #pragma once
18
19 #include <folly/futures/Future.h>
20 #include <folly/futures/SharedPromise.h>
21
22 namespace folly {
23
24 /*
25  * FutureSplitter provides a `getFuture()' method which can be called multiple
26  * times, returning a new Future each time. These futures are called-back when
27  * the original Future passed to the FutureSplitter constructor completes. Calls
28  * to `getFuture()' after that time return a completed Future.
29  *
30  * Note that while the Futures from `getFuture()' depend on the completion of
31  * the original Future they do not inherit any other properties such as
32  * Executors passed to `via' etc.
33  */
34 template <class T>
35 class FutureSplitter {
36  public:
37   /**
38    * Default constructor for convenience only. It is an error to call
39    * `getFuture()` on a default-constructed FutureSplitter which has not had
40    * a correctly-constructed FutureSplitter copy- or move-assigned into it.
41    */
42   FutureSplitter() = default;
43
44   /**
45    * Provide a way to split a Future<T>.
46    */
47   explicit FutureSplitter(Future<T>&& future)
48       : promise_(std::make_shared<SharedPromise<T>>()) {
49     future.then([promise = promise_](Try<T> && theTry) {
50       promise->setTry(std::move(theTry));
51     });
52   }
53
54   /**
55    * This can be called an unlimited number of times per FutureSplitter.
56    */
57   Future<T> getFuture() {
58     if (UNLIKELY(promise_ == nullptr)) {
59       throw NoFutureInSplitter();
60     }
61     return promise_->getFuture();
62   }
63
64  private:
65   std::shared_ptr<SharedPromise<T>> promise_;
66 };
67
68 /**
69  * Convenience function, allowing us to exploit template argument deduction to
70  * improve readability.
71  */
72 template <class T>
73 FutureSplitter<T> splitFuture(Future<T>&& future) {
74   return FutureSplitter<T>{std::move(future)};
75 }
76 }