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