Mercurial > repos > rliterman > csp2
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 |