comparison CSP2/CSP2_env/env-d9b9114564458d9d-741b3de822f2aaca6c6caa4325c4afce/include/kj/function.h @ 69:33d812a61356

planemo upload commit 2e9511a184a1ca667c7be0c6321a36dc4e3d116d
author jpayne
date Tue, 18 Mar 2025 17:55:14 -0400
parents
children
comparison
equal deleted inserted replaced
67:0e9998148a16 69:33d812a61356
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>
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
118 inline Return operator()(Params... params) {
119 return (*impl)(kj::fwd<Params>(params)...);
120 }
121
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:
139 explicit Impl(F&& f): f(kj::fwd<F>(f)) {}
140
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>
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
171 inline Return operator()(Params... params) const {
172 return (*impl)(kj::fwd<Params>(params)...);
173 }
174
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:
192 explicit Impl(F&& f): f(kj::fwd<F>(f)) {}
193
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>
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
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:
242 Wrapper(Func& func): func(func) {}
243
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:
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>
262 auto operator()(Params&&... params) {
263 return func(t, kj::fwd<Params>(params)...);
264 }
265 template <typename... Params>
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>
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