1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
2 // Licensed under the MIT License:
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a copy
5 // of this software and associated documentation files (the "Software"), to deal
6 // in the Software without restriction, including without limitation the rights
7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 // copies of the Software, and to permit persons to whom the Software is
9 // furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 // THE SOFTWARE.
21 
22 #pragma once
23 
24 #include "memory.h"
25 
26 KJ_BEGIN_HEADER
27 
28 namespace kj {
29 
30 template <typename Signature>
31 class Function;
32 // Function wrapper using virtual-based polymorphism.  Use this when template polymorphism is
33 // not possible.  You can, for example, accept a Function as a parameter:
34 //
35 //     void setFilter(Function<bool(const Widget&)> filter);
36 //
37 // The caller of `setFilter()` may then pass any callable object as the parameter.  The callable
38 // object does not have to have the exact signature specified, just one that is "compatible" --
39 // i.e. the return type is covariant and the parameters are contravariant.
40 //
41 // Unlike `std::function`, `kj::Function`s are movable but not copyable, just like `kj::Own`.  This
42 // is to avoid unexpected heap allocation or slow atomic reference counting.
43 //
44 // When a `Function` is constructed from an lvalue, it captures only a reference to the value.
45 // When constructed from an rvalue, it invokes the value's move constructor.  So, for example:
46 //
47 //     struct AddN {
48 //       int n;
49 //       int operator(int i) { return i + n; }
50 //     }
51 //
52 //     Function<int(int, int)> f1 = AddN{2};
53 //     // f1 owns an instance of AddN.  It may safely be moved out
54 //     // of the local scope.
55 //
56 //     AddN adder(2);
57 //     Function<int(int, int)> f2 = adder;
58 //     // f2 contains a reference to `adder`.  Thus, it becomes invalid
59 //     // when `adder` goes out-of-scope.
60 //
61 //     AddN adder2(2);
62 //     Function<int(int, int)> f3 = kj::mv(adder2);
63 //     // f3 owns an insatnce of AddN moved from `adder2`.  f3 may safely
64 //     // be moved out of the local scope.
65 //
66 // Additionally, a Function may be bound to a class method using KJ_BIND_METHOD(object, methodName).
67 // For example:
68 //
69 //     class Printer {
70 //     public:
71 //       void print(int i);
72 //       void print(kj::StringPtr s);
73 //     };
74 //
75 //     Printer p;
76 //
77 //     Function<void(uint)> intPrinter = KJ_BIND_METHOD(p, print);
78 //     // Will call Printer::print(int).
79 //
80 //     Function<void(const char*)> strPrinter = KJ_BIND_METHOD(p, print);
81 //     // Will call Printer::print(kj::StringPtr).
82 //
83 // Notice how KJ_BIND_METHOD is able to figure out which overload to use depending on the kind of
84 // Function it is binding to.
85 
86 template <typename Signature>
87 class ConstFunction;
88 // Like Function, but wraps a "const" (i.e. thread-safe) call.
89 
90 template <typename Signature>
91 class FunctionParam;
92 // Like Function, but used specifically as a call parameter type. Does not do any heap allocation.
93 //
94 // This type MUST NOT be used for anything other than a parameter type to a function or method.
95 // This is because if FunctionParam binds to a temporary, it assumes that the temporary will
96 // outlive the FunctionParam instance. This is true when FunctionParam is used as a parameter type,
97 // but not if it is used as a local variable nor a class member variable.
98 
99 template <typename Return, typename... Params>
100 class Function<Return(Params...)> {
101 public:
102   template <typename F>
Function(F && f)103   inline Function(F&& f): impl(heap<Impl<F>>(kj::fwd<F>(f))) {}
104   Function() = default;
105 
106   // Make sure people don't accidentally end up wrapping a reference when they meant to return
107   // a function.
108   KJ_DISALLOW_COPY(Function);
109   Function(Function&) = delete;
110   Function& operator=(Function&) = delete;
111   template <typename T> Function(const Function<T>&) = delete;
112   template <typename T> Function& operator=(const Function<T>&) = delete;
113   template <typename T> Function(const ConstFunction<T>&) = delete;
114   template <typename T> Function& operator=(const ConstFunction<T>&) = delete;
115   Function(Function&&) = default;
116   Function& operator=(Function&&) = default;
117 
operator()118   inline Return operator()(Params... params) {
119     return (*impl)(kj::fwd<Params>(params)...);
120   }
121 
reference()122   Function reference() {
123     // Forms a new Function of the same type that delegates to this Function by reference.
124     // Therefore, this Function must outlive the returned Function, but otherwise they behave
125     // exactly the same.
126 
127     return *impl;
128   }
129 
130 private:
131   class Iface {
132   public:
133     virtual Return operator()(Params... params) = 0;
134   };
135 
136   template <typename F>
137   class Impl final: public Iface {
138   public:
Impl(F && f)139     explicit Impl(F&& f): f(kj::fwd<F>(f)) {}
140 
operator()141     Return operator()(Params... params) override {
142       return f(kj::fwd<Params>(params)...);
143     }
144 
145   private:
146     F f;
147   };
148 
149   Own<Iface> impl;
150 };
151 
152 template <typename Return, typename... Params>
153 class ConstFunction<Return(Params...)> {
154 public:
155   template <typename F>
ConstFunction(F && f)156   inline ConstFunction(F&& f): impl(heap<Impl<F>>(kj::fwd<F>(f))) {}
157   ConstFunction() = default;
158 
159   // Make sure people don't accidentally end up wrapping a reference when they meant to return
160   // a function.
161   KJ_DISALLOW_COPY(ConstFunction);
162   ConstFunction(ConstFunction&) = delete;
163   ConstFunction& operator=(ConstFunction&) = delete;
164   template <typename T> ConstFunction(const ConstFunction<T>&) = delete;
165   template <typename T> ConstFunction& operator=(const ConstFunction<T>&) = delete;
166   template <typename T> ConstFunction(const Function<T>&) = delete;
167   template <typename T> ConstFunction& operator=(const Function<T>&) = delete;
168   ConstFunction(ConstFunction&&) = default;
169   ConstFunction& operator=(ConstFunction&&) = default;
170 
operator()171   inline Return operator()(Params... params) const {
172     return (*impl)(kj::fwd<Params>(params)...);
173   }
174 
reference()175   ConstFunction reference() const {
176     // Forms a new ConstFunction of the same type that delegates to this ConstFunction by reference.
177     // Therefore, this ConstFunction must outlive the returned ConstFunction, but otherwise they
178     // behave exactly the same.
179 
180     return *impl;
181   }
182 
183 private:
184   class Iface {
185   public:
186     virtual Return operator()(Params... params) const = 0;
187   };
188 
189   template <typename F>
190   class Impl final: public Iface {
191   public:
Impl(F && f)192     explicit Impl(F&& f): f(kj::fwd<F>(f)) {}
193 
operator()194     Return operator()(Params... params) const override {
195       return f(kj::fwd<Params>(params)...);
196     }
197 
198   private:
199     F f;
200   };
201 
202   Own<Iface> impl;
203 };
204 
205 template <typename Return, typename... Params>
206 class FunctionParam<Return(Params...)> {
207 public:
208   template <typename Func>
FunctionParam(Func && func)209   FunctionParam(Func&& func) {
210     typedef Wrapper<Decay<Func>> WrapperType;
211 
212     // All instances of Wrapper<Func> are two pointers in size: a vtable, and a Func&. So if we
213     // allocate space for two pointers, we can construct a Wrapper<Func> in it!
214     static_assert(sizeof(WrapperType) == sizeof(space),
215         "expected WrapperType to be two pointers");
216 
217     // Even if `func` is an rvalue reference, it's OK to use it as an lvalue here, because
218     // FunctionParam is used strictly for parameters. If we captured a temporary, we know that
219     // temporary will not be destroyed until after the function call completes.
220     ctor(*reinterpret_cast<WrapperType*>(space), func);
221   }
222 
223   FunctionParam(const FunctionParam& other) = default;
224   FunctionParam(FunctionParam&& other) = default;
225   // Magically, a plain copy works.
226 
operator()227   inline Return operator()(Params... params) {
228     return (*reinterpret_cast<WrapperBase*>(space))(kj::fwd<Params>(params)...);
229   }
230 
231 private:
232   alignas(void*) char space[2 * sizeof(void*)];
233 
234   class WrapperBase {
235   public:
236     virtual Return operator()(Params... params) = 0;
237   };
238 
239   template <typename Func>
240   class Wrapper: public WrapperBase {
241   public:
Wrapper(Func & func)242     Wrapper(Func& func): func(func) {}
243 
operator()244     inline Return operator()(Params... params) override {
245       return func(kj::fwd<Params>(params)...);
246     }
247 
248   private:
249     Func& func;
250   };
251 };
252 
253 namespace _ {  // private
254 
255 template <typename T, typename Func, typename ConstFunc>
256 class BoundMethod {
257 public:
BoundMethod(T && t,Func && func,ConstFunc && constFunc)258   BoundMethod(T&& t, Func&& func, ConstFunc&& constFunc)
259       : t(kj::fwd<T>(t)), func(kj::mv(func)), constFunc(kj::mv(constFunc)) {}
260 
261   template <typename... Params>
operator()262   auto operator()(Params&&... params) {
263     return func(t, kj::fwd<Params>(params)...);
264   }
265   template <typename... Params>
operator()266   auto operator()(Params&&... params) const {
267     return constFunc(t, kj::fwd<Params>(params)...);
268   }
269 
270 private:
271   T t;
272   Func func;
273   ConstFunc constFunc;
274 };
275 
276 template <typename T, typename Func, typename ConstFunc>
boundMethod(T && t,Func && func,ConstFunc && constFunc)277 BoundMethod<T, Func, ConstFunc> boundMethod(T&& t, Func&& func, ConstFunc&& constFunc) {
278   return { kj::fwd<T>(t), kj::fwd<Func>(func), kj::fwd<ConstFunc>(constFunc) };
279 }
280 
281 }  // namespace _ (private)
282 
283 #define KJ_BIND_METHOD(obj, method) \
284   ::kj::_::boundMethod(obj, \
285       [](auto& s, auto&&... p) mutable { return s.method(kj::fwd<decltype(p)>(p)...); }, \
286       [](auto& s, auto&&... p) { return s.method(kj::fwd<decltype(p)>(p)...); })
287 // Macro that produces a functor object which forwards to the method `obj.name`.  If `obj` is an
288 // lvalue, the functor will hold a reference to it.  If `obj` is an rvalue, the functor will
289 // contain a copy (by move) of it. The method is allowed to be overloaded.
290 
291 }  // namespace kj
292 
293 KJ_END_HEADER
294