Fix #includes
[folly.git] / folly / wangle / OpaqueCallbackShunt.h
1 /*
2  * Copyright 2014 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/wangle/Promise.h>
20
21 namespace folly { namespace wangle {
22
23 /// These classes help you wrap an existing C style callback function
24 /// into a Future/Later.
25 ///
26 ///   void legacy_send_async(..., void (*cb)(void*), void*);
27 ///
28 ///   Future<T> wrappedSendAsync(T&& obj) {
29 ///     auto handle = new OpaqueCallbackShunt<T>(obj);
30 ///     auto future = handle->promise_.getFuture();
31 ///     legacy_send_async(..., OpaqueCallbackShunt<T>::callback, handle)
32 ///     return future;
33 ///   }
34 ///
35 /// If the legacy function doesn't conform to void (*cb)(void*), use a lambda:
36 ///
37 ///   auto cb = [](t1*, t2*, void* arg) {
38 ///     OpaqueCallbackShunt<T>::callback(arg);
39 ///   };
40 ///   legacy_send_async(..., cb, handle);
41
42 template <typename T>
43 class OpaqueCallbackShunt {
44 public:
45   explicit OpaqueCallbackShunt(T&& obj)
46     : obj_(std::move(obj)) { }
47   static void callback(void* arg) {
48     std::unique_ptr<OpaqueCallbackShunt<T>> handle(
49       static_cast<OpaqueCallbackShunt<T>*>(arg));
50     handle->promise_.setValue(std::move(handle->obj_));
51   }
52   folly::wangle::Promise<T> promise_;
53 private:
54   T obj_;
55 };
56
57 /// Variant that returns a Later instead of a Future
58 ///
59 ///   Later<int> wrappedSendAsyncLater(int i) {
60 ///     folly::MoveWrapper<int> wrapped(std::move(i));
61 ///     return Later<int>(
62 ///       [..., wrapped](std::function<void(int&&)>&& fn) mutable {
63 ///         auto handle = new OpaqueCallbackLaterShunt<int>(
64 ///           std::move(*wrapped), std::move(fn));
65 ///         legacy_send_async(...,
66 ///          OpaqueCallbackLaterShunt<int>::callback, handle);
67 ///       });
68 ///   }
69 ///
70 /// Depending on your compiler's kung-fu knowledge, you might need to assign
71 /// the lambda to a std::function<void(std::function<void(int&&)>&&)> temporary
72 /// variable before std::moving into it into the later.
73
74 template <typename T>
75 class OpaqueCallbackLaterShunt {
76 public:
77   explicit
78   OpaqueCallbackLaterShunt(T&& obj, std::function<void(T&&)>&& fn)
79    : fn_(std::move(fn)), obj_(std::move(obj)) { }
80   static void callback(void* arg) {
81     std::unique_ptr<OpaqueCallbackLaterShunt<T>> handle(
82       static_cast<OpaqueCallbackLaterShunt<T>*>(arg));
83     handle->fn_(std::move(handle->obj_));
84   }
85 private:
86   std::function<void(T&&)> fn_;
87   T obj_;
88 };
89
90 }} // folly::wangle