Mercurial > hg > sv-dependency-builds
comparison osx/include/kj/async-inl.h @ 49:3ab5a40c4e3b
Add Capnp and KJ builds for OSX
author | Chris Cannam <cannam@all-day-breakfast.com> |
---|---|
date | Tue, 25 Oct 2016 14:48:23 +0100 |
parents | |
children | 0994c39f1e94 |
comparison
equal
deleted
inserted
replaced
48:9530b331f8c1 | 49:3ab5a40c4e3b |
---|---|
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 // This file contains extended inline implementation details that are required along with async.h. | |
23 // We move this all into a separate file to make async.h more readable. | |
24 // | |
25 // Non-inline declarations here are defined in async.c++. | |
26 | |
27 #ifndef KJ_ASYNC_H_ | |
28 #error "Do not include this directly; include kj/async.h." | |
29 #include "async.h" // help IDE parse this file | |
30 #endif | |
31 | |
32 #ifndef KJ_ASYNC_INL_H_ | |
33 #define KJ_ASYNC_INL_H_ | |
34 | |
35 #if defined(__GNUC__) && !KJ_HEADER_WARNINGS | |
36 #pragma GCC system_header | |
37 #endif | |
38 | |
39 namespace kj { | |
40 namespace _ { // private | |
41 | |
42 template <typename T> | |
43 class ExceptionOr; | |
44 | |
45 class ExceptionOrValue { | |
46 public: | |
47 ExceptionOrValue(bool, Exception&& exception): exception(kj::mv(exception)) {} | |
48 KJ_DISALLOW_COPY(ExceptionOrValue); | |
49 | |
50 void addException(Exception&& exception) { | |
51 if (this->exception == nullptr) { | |
52 this->exception = kj::mv(exception); | |
53 } | |
54 } | |
55 | |
56 template <typename T> | |
57 ExceptionOr<T>& as() { return *static_cast<ExceptionOr<T>*>(this); } | |
58 template <typename T> | |
59 const ExceptionOr<T>& as() const { return *static_cast<const ExceptionOr<T>*>(this); } | |
60 | |
61 Maybe<Exception> exception; | |
62 | |
63 protected: | |
64 // Allow subclasses to have move constructor / assignment. | |
65 ExceptionOrValue() = default; | |
66 ExceptionOrValue(ExceptionOrValue&& other) = default; | |
67 ExceptionOrValue& operator=(ExceptionOrValue&& other) = default; | |
68 }; | |
69 | |
70 template <typename T> | |
71 class ExceptionOr: public ExceptionOrValue { | |
72 public: | |
73 ExceptionOr() = default; | |
74 ExceptionOr(T&& value): value(kj::mv(value)) {} | |
75 ExceptionOr(bool, Exception&& exception): ExceptionOrValue(false, kj::mv(exception)) {} | |
76 ExceptionOr(ExceptionOr&&) = default; | |
77 ExceptionOr& operator=(ExceptionOr&&) = default; | |
78 | |
79 Maybe<T> value; | |
80 }; | |
81 | |
82 class Event { | |
83 // An event waiting to be executed. Not for direct use by applications -- promises use this | |
84 // internally. | |
85 | |
86 public: | |
87 Event(); | |
88 ~Event() noexcept(false); | |
89 KJ_DISALLOW_COPY(Event); | |
90 | |
91 void armDepthFirst(); | |
92 // Enqueue this event so that `fire()` will be called from the event loop soon. | |
93 // | |
94 // Events scheduled in this way are executed in depth-first order: if an event callback arms | |
95 // more events, those events are placed at the front of the queue (in the order in which they | |
96 // were armed), so that they run immediately after the first event's callback returns. | |
97 // | |
98 // Depth-first event scheduling is appropriate for events that represent simple continuations | |
99 // of a previous event that should be globbed together for performance. Depth-first scheduling | |
100 // can lead to starvation, so any long-running task must occasionally yield with | |
101 // `armBreadthFirst()`. (Promise::then() uses depth-first whereas evalLater() uses | |
102 // breadth-first.) | |
103 // | |
104 // To use breadth-first scheduling instead, use `armBreadthFirst()`. | |
105 | |
106 void armBreadthFirst(); | |
107 // Like `armDepthFirst()` except that the event is placed at the end of the queue. | |
108 | |
109 kj::String trace(); | |
110 // Dump debug info about this event. | |
111 | |
112 virtual _::PromiseNode* getInnerForTrace(); | |
113 // If this event wraps a PromiseNode, get that node. Used for debug tracing. | |
114 // Default implementation returns nullptr. | |
115 | |
116 protected: | |
117 virtual Maybe<Own<Event>> fire() = 0; | |
118 // Fire the event. Possibly returns a pointer to itself, which will be discarded by the | |
119 // caller. This is the only way that an event can delete itself as a result of firing, as | |
120 // doing so from within fire() will throw an exception. | |
121 | |
122 private: | |
123 friend class kj::EventLoop; | |
124 EventLoop& loop; | |
125 Event* next; | |
126 Event** prev; | |
127 bool firing = false; | |
128 }; | |
129 | |
130 class PromiseNode { | |
131 // A Promise<T> contains a chain of PromiseNodes tracking the pending transformations. | |
132 // | |
133 // To reduce generated code bloat, PromiseNode is not a template. Instead, it makes very hacky | |
134 // use of pointers to ExceptionOrValue which actually point to ExceptionOr<T>, but are only | |
135 // so down-cast in the few places that really need to be templated. Luckily this is all | |
136 // internal implementation details. | |
137 | |
138 public: | |
139 virtual void onReady(Event& event) noexcept = 0; | |
140 // Arms the given event when ready. | |
141 | |
142 virtual void setSelfPointer(Own<PromiseNode>* selfPtr) noexcept; | |
143 // Tells the node that `selfPtr` is the pointer that owns this node, and will continue to own | |
144 // this node until it is destroyed or setSelfPointer() is called again. ChainPromiseNode uses | |
145 // this to shorten redundant chains. The default implementation does nothing; only | |
146 // ChainPromiseNode should implement this. | |
147 | |
148 virtual void get(ExceptionOrValue& output) noexcept = 0; | |
149 // Get the result. `output` points to an ExceptionOr<T> into which the result will be written. | |
150 // Can only be called once, and only after the node is ready. Must be called directly from the | |
151 // event loop, with no application code on the stack. | |
152 | |
153 virtual PromiseNode* getInnerForTrace(); | |
154 // If this node wraps some other PromiseNode, get the wrapped node. Used for debug tracing. | |
155 // Default implementation returns nullptr. | |
156 | |
157 protected: | |
158 class OnReadyEvent { | |
159 // Helper class for implementing onReady(). | |
160 | |
161 public: | |
162 void init(Event& newEvent); | |
163 // Returns true if arm() was already called. | |
164 | |
165 void arm(); | |
166 // Arms the event if init() has already been called and makes future calls to init() return | |
167 // true. | |
168 | |
169 private: | |
170 Event* event = nullptr; | |
171 }; | |
172 }; | |
173 | |
174 // ------------------------------------------------------------------- | |
175 | |
176 class ImmediatePromiseNodeBase: public PromiseNode { | |
177 public: | |
178 ImmediatePromiseNodeBase(); | |
179 ~ImmediatePromiseNodeBase() noexcept(false); | |
180 | |
181 void onReady(Event& event) noexcept override; | |
182 }; | |
183 | |
184 template <typename T> | |
185 class ImmediatePromiseNode final: public ImmediatePromiseNodeBase { | |
186 // A promise that has already been resolved to an immediate value or exception. | |
187 | |
188 public: | |
189 ImmediatePromiseNode(ExceptionOr<T>&& result): result(kj::mv(result)) {} | |
190 | |
191 void get(ExceptionOrValue& output) noexcept override { | |
192 output.as<T>() = kj::mv(result); | |
193 } | |
194 | |
195 private: | |
196 ExceptionOr<T> result; | |
197 }; | |
198 | |
199 class ImmediateBrokenPromiseNode final: public ImmediatePromiseNodeBase { | |
200 public: | |
201 ImmediateBrokenPromiseNode(Exception&& exception); | |
202 | |
203 void get(ExceptionOrValue& output) noexcept override; | |
204 | |
205 private: | |
206 Exception exception; | |
207 }; | |
208 | |
209 // ------------------------------------------------------------------- | |
210 | |
211 class AttachmentPromiseNodeBase: public PromiseNode { | |
212 public: | |
213 AttachmentPromiseNodeBase(Own<PromiseNode>&& dependency); | |
214 | |
215 void onReady(Event& event) noexcept override; | |
216 void get(ExceptionOrValue& output) noexcept override; | |
217 PromiseNode* getInnerForTrace() override; | |
218 | |
219 private: | |
220 Own<PromiseNode> dependency; | |
221 | |
222 void dropDependency(); | |
223 | |
224 template <typename> | |
225 friend class AttachmentPromiseNode; | |
226 }; | |
227 | |
228 template <typename Attachment> | |
229 class AttachmentPromiseNode final: public AttachmentPromiseNodeBase { | |
230 // A PromiseNode that holds on to some object (usually, an Own<T>, but could be any movable | |
231 // object) until the promise resolves. | |
232 | |
233 public: | |
234 AttachmentPromiseNode(Own<PromiseNode>&& dependency, Attachment&& attachment) | |
235 : AttachmentPromiseNodeBase(kj::mv(dependency)), | |
236 attachment(kj::mv<Attachment>(attachment)) {} | |
237 | |
238 ~AttachmentPromiseNode() noexcept(false) { | |
239 // We need to make sure the dependency is deleted before we delete the attachment because the | |
240 // dependency may be using the attachment. | |
241 dropDependency(); | |
242 } | |
243 | |
244 private: | |
245 Attachment attachment; | |
246 }; | |
247 | |
248 // ------------------------------------------------------------------- | |
249 | |
250 class PtmfHelper { | |
251 // This class is a private helper for GetFunctorStartAddress. The class represents the internal | |
252 // representation of a pointer-to-member-function. | |
253 | |
254 template <typename... ParamTypes> | |
255 friend struct GetFunctorStartAddress; | |
256 | |
257 #if __GNUG__ | |
258 void* ptr; | |
259 ptrdiff_t adj; | |
260 // Layout of a pointer-to-member-function used by GCC and compatible compilers. | |
261 #else | |
262 #error "TODO(port): PTMF instruction address extraction" | |
263 #endif | |
264 | |
265 #define BODY \ | |
266 PtmfHelper result; \ | |
267 static_assert(sizeof(p) == sizeof(result), "unknown ptmf layout"); \ | |
268 memcpy(&result, &p, sizeof(result)); \ | |
269 return result | |
270 | |
271 template <typename R, typename C, typename... P, typename F> | |
272 static PtmfHelper from(F p) { BODY; } | |
273 // Create a PtmfHelper from some arbitrary pointer-to-member-function which is not | |
274 // overloaded nor a template. In this case the compiler is able to deduce the full function | |
275 // signature directly given the name since there is only one function with that name. | |
276 | |
277 template <typename R, typename C, typename... P> | |
278 static PtmfHelper from(R (C::*p)(NoInfer<P>...)) { BODY; } | |
279 template <typename R, typename C, typename... P> | |
280 static PtmfHelper from(R (C::*p)(NoInfer<P>...) const) { BODY; } | |
281 // Create a PtmfHelper from some poniter-to-member-function which is a template. In this case | |
282 // the function must match exactly the containing type C, return type R, and parameter types P... | |
283 // GetFunctorStartAddress normally specifies exactly the correct C and R, but can only make a | |
284 // guess at P. Luckily, if the function parameters are template parameters then it's not | |
285 // necessary to be precise about P. | |
286 #undef BODY | |
287 | |
288 void* apply(void* obj) { | |
289 #if defined(__arm__) || defined(__mips__) || defined(__aarch64__) | |
290 if (adj & 1) { | |
291 ptrdiff_t voff = (ptrdiff_t)ptr; | |
292 #else | |
293 ptrdiff_t voff = (ptrdiff_t)ptr; | |
294 if (voff & 1) { | |
295 voff &= ~1; | |
296 #endif | |
297 return *(void**)(*(char**)obj + voff); | |
298 } else { | |
299 return ptr; | |
300 } | |
301 } | |
302 }; | |
303 | |
304 template <typename... ParamTypes> | |
305 struct GetFunctorStartAddress { | |
306 // Given a functor (any object defining operator()), return the start address of the function, | |
307 // suitable for passing to addr2line to obtain a source file/line for debugging purposes. | |
308 // | |
309 // This turns out to be incredibly hard to implement in the presence of overloaded or templated | |
310 // functors. Therefore, we impose these specific restrictions, specific to our use case: | |
311 // - Overloading is not allowed, but templating is. (Generally we only intend to support lambdas | |
312 // anyway.) | |
313 // - The template parameters to GetFunctorStartAddress specify a hint as to the expected | |
314 // parameter types. If the functor is templated, its parameters must match exactly these types. | |
315 // (If it's not templated, ParamTypes are ignored.) | |
316 | |
317 template <typename Func> | |
318 static void* apply(Func&& func) { | |
319 typedef decltype(func(instance<ParamTypes>()...)) ReturnType; | |
320 return PtmfHelper::from<ReturnType, Decay<Func>, ParamTypes...>( | |
321 &Decay<Func>::operator()).apply(&func); | |
322 } | |
323 }; | |
324 | |
325 template <> | |
326 struct GetFunctorStartAddress<Void&&>: public GetFunctorStartAddress<> {}; | |
327 // Hack for TransformPromiseNode use case: an input type of `Void` indicates that the function | |
328 // actually has no parameters. | |
329 | |
330 class TransformPromiseNodeBase: public PromiseNode { | |
331 public: | |
332 TransformPromiseNodeBase(Own<PromiseNode>&& dependency, void* continuationTracePtr); | |
333 | |
334 void onReady(Event& event) noexcept override; | |
335 void get(ExceptionOrValue& output) noexcept override; | |
336 PromiseNode* getInnerForTrace() override; | |
337 | |
338 private: | |
339 Own<PromiseNode> dependency; | |
340 void* continuationTracePtr; | |
341 | |
342 void dropDependency(); | |
343 void getDepResult(ExceptionOrValue& output); | |
344 | |
345 virtual void getImpl(ExceptionOrValue& output) = 0; | |
346 | |
347 template <typename, typename, typename, typename> | |
348 friend class TransformPromiseNode; | |
349 }; | |
350 | |
351 template <typename T, typename DepT, typename Func, typename ErrorFunc> | |
352 class TransformPromiseNode final: public TransformPromiseNodeBase { | |
353 // A PromiseNode that transforms the result of another PromiseNode through an application-provided | |
354 // function (implements `then()`). | |
355 | |
356 public: | |
357 TransformPromiseNode(Own<PromiseNode>&& dependency, Func&& func, ErrorFunc&& errorHandler) | |
358 : TransformPromiseNodeBase(kj::mv(dependency), | |
359 GetFunctorStartAddress<DepT&&>::apply(func)), | |
360 func(kj::fwd<Func>(func)), errorHandler(kj::fwd<ErrorFunc>(errorHandler)) {} | |
361 | |
362 ~TransformPromiseNode() noexcept(false) { | |
363 // We need to make sure the dependency is deleted before we delete the continuations because it | |
364 // is a common pattern for the continuations to hold ownership of objects that might be in-use | |
365 // by the dependency. | |
366 dropDependency(); | |
367 } | |
368 | |
369 private: | |
370 Func func; | |
371 ErrorFunc errorHandler; | |
372 | |
373 void getImpl(ExceptionOrValue& output) override { | |
374 ExceptionOr<DepT> depResult; | |
375 getDepResult(depResult); | |
376 KJ_IF_MAYBE(depException, depResult.exception) { | |
377 output.as<T>() = handle( | |
378 MaybeVoidCaller<Exception, FixVoid<ReturnType<ErrorFunc, Exception>>>::apply( | |
379 errorHandler, kj::mv(*depException))); | |
380 } else KJ_IF_MAYBE(depValue, depResult.value) { | |
381 output.as<T>() = handle(MaybeVoidCaller<DepT, T>::apply(func, kj::mv(*depValue))); | |
382 } | |
383 } | |
384 | |
385 ExceptionOr<T> handle(T&& value) { | |
386 return kj::mv(value); | |
387 } | |
388 ExceptionOr<T> handle(PropagateException::Bottom&& value) { | |
389 return ExceptionOr<T>(false, value.asException()); | |
390 } | |
391 }; | |
392 | |
393 // ------------------------------------------------------------------- | |
394 | |
395 class ForkHubBase; | |
396 | |
397 class ForkBranchBase: public PromiseNode { | |
398 public: | |
399 ForkBranchBase(Own<ForkHubBase>&& hub); | |
400 ~ForkBranchBase() noexcept(false); | |
401 | |
402 void hubReady() noexcept; | |
403 // Called by the hub to indicate that it is ready. | |
404 | |
405 // implements PromiseNode ------------------------------------------ | |
406 void onReady(Event& event) noexcept override; | |
407 PromiseNode* getInnerForTrace() override; | |
408 | |
409 protected: | |
410 inline ExceptionOrValue& getHubResultRef(); | |
411 | |
412 void releaseHub(ExceptionOrValue& output); | |
413 // Release the hub. If an exception is thrown, add it to `output`. | |
414 | |
415 private: | |
416 OnReadyEvent onReadyEvent; | |
417 | |
418 Own<ForkHubBase> hub; | |
419 ForkBranchBase* next = nullptr; | |
420 ForkBranchBase** prevPtr = nullptr; | |
421 | |
422 friend class ForkHubBase; | |
423 }; | |
424 | |
425 template <typename T> T copyOrAddRef(T& t) { return t; } | |
426 template <typename T> Own<T> copyOrAddRef(Own<T>& t) { return t->addRef(); } | |
427 | |
428 template <typename T> | |
429 class ForkBranch final: public ForkBranchBase { | |
430 // A PromiseNode that implements one branch of a fork -- i.e. one of the branches that receives | |
431 // a const reference. | |
432 | |
433 public: | |
434 ForkBranch(Own<ForkHubBase>&& hub): ForkBranchBase(kj::mv(hub)) {} | |
435 | |
436 void get(ExceptionOrValue& output) noexcept override { | |
437 ExceptionOr<T>& hubResult = getHubResultRef().template as<T>(); | |
438 KJ_IF_MAYBE(value, hubResult.value) { | |
439 output.as<T>().value = copyOrAddRef(*value); | |
440 } else { | |
441 output.as<T>().value = nullptr; | |
442 } | |
443 output.exception = hubResult.exception; | |
444 releaseHub(output); | |
445 } | |
446 }; | |
447 | |
448 template <typename T, size_t index> | |
449 class SplitBranch final: public ForkBranchBase { | |
450 // A PromiseNode that implements one branch of a fork -- i.e. one of the branches that receives | |
451 // a const reference. | |
452 | |
453 public: | |
454 SplitBranch(Own<ForkHubBase>&& hub): ForkBranchBase(kj::mv(hub)) {} | |
455 | |
456 typedef kj::Decay<decltype(kj::get<index>(kj::instance<T>()))> Element; | |
457 | |
458 void get(ExceptionOrValue& output) noexcept override { | |
459 ExceptionOr<T>& hubResult = getHubResultRef().template as<T>(); | |
460 KJ_IF_MAYBE(value, hubResult.value) { | |
461 output.as<Element>().value = kj::mv(kj::get<index>(*value)); | |
462 } else { | |
463 output.as<Element>().value = nullptr; | |
464 } | |
465 output.exception = hubResult.exception; | |
466 releaseHub(output); | |
467 } | |
468 }; | |
469 | |
470 // ------------------------------------------------------------------- | |
471 | |
472 class ForkHubBase: public Refcounted, protected Event { | |
473 public: | |
474 ForkHubBase(Own<PromiseNode>&& inner, ExceptionOrValue& resultRef); | |
475 | |
476 inline ExceptionOrValue& getResultRef() { return resultRef; } | |
477 | |
478 private: | |
479 Own<PromiseNode> inner; | |
480 ExceptionOrValue& resultRef; | |
481 | |
482 ForkBranchBase* headBranch = nullptr; | |
483 ForkBranchBase** tailBranch = &headBranch; | |
484 // Tail becomes null once the inner promise is ready and all branches have been notified. | |
485 | |
486 Maybe<Own<Event>> fire() override; | |
487 _::PromiseNode* getInnerForTrace() override; | |
488 | |
489 friend class ForkBranchBase; | |
490 }; | |
491 | |
492 template <typename T> | |
493 class ForkHub final: public ForkHubBase { | |
494 // A PromiseNode that implements the hub of a fork. The first call to Promise::fork() replaces | |
495 // the promise's outer node with a ForkHub, and subsequent calls add branches to that hub (if | |
496 // possible). | |
497 | |
498 public: | |
499 ForkHub(Own<PromiseNode>&& inner): ForkHubBase(kj::mv(inner), result) {} | |
500 | |
501 Promise<_::UnfixVoid<T>> addBranch() { | |
502 return Promise<_::UnfixVoid<T>>(false, kj::heap<ForkBranch<T>>(addRef(*this))); | |
503 } | |
504 | |
505 _::SplitTuplePromise<T> split() { | |
506 return splitImpl(MakeIndexes<tupleSize<T>()>()); | |
507 } | |
508 | |
509 private: | |
510 ExceptionOr<T> result; | |
511 | |
512 template <size_t... indexes> | |
513 _::SplitTuplePromise<T> splitImpl(Indexes<indexes...>) { | |
514 return kj::tuple(addSplit<indexes>()...); | |
515 } | |
516 | |
517 template <size_t index> | |
518 Promise<JoinPromises<typename SplitBranch<T, index>::Element>> addSplit() { | |
519 return Promise<JoinPromises<typename SplitBranch<T, index>::Element>>( | |
520 false, maybeChain(kj::heap<SplitBranch<T, index>>(addRef(*this)), | |
521 implicitCast<typename SplitBranch<T, index>::Element*>(nullptr))); | |
522 } | |
523 }; | |
524 | |
525 inline ExceptionOrValue& ForkBranchBase::getHubResultRef() { | |
526 return hub->getResultRef(); | |
527 } | |
528 | |
529 // ------------------------------------------------------------------- | |
530 | |
531 class ChainPromiseNode final: public PromiseNode, public Event { | |
532 // Promise node which reduces Promise<Promise<T>> to Promise<T>. | |
533 // | |
534 // `Event` is only a public base class because otherwise we can't cast Own<ChainPromiseNode> to | |
535 // Own<Event>. Ugh, templates and private... | |
536 | |
537 public: | |
538 explicit ChainPromiseNode(Own<PromiseNode> inner); | |
539 ~ChainPromiseNode() noexcept(false); | |
540 | |
541 void onReady(Event& event) noexcept override; | |
542 void setSelfPointer(Own<PromiseNode>* selfPtr) noexcept override; | |
543 void get(ExceptionOrValue& output) noexcept override; | |
544 PromiseNode* getInnerForTrace() override; | |
545 | |
546 private: | |
547 enum State { | |
548 STEP1, | |
549 STEP2 | |
550 }; | |
551 | |
552 State state; | |
553 | |
554 Own<PromiseNode> inner; | |
555 // In STEP1, a PromiseNode for a Promise<T>. | |
556 // In STEP2, a PromiseNode for a T. | |
557 | |
558 Event* onReadyEvent = nullptr; | |
559 Own<PromiseNode>* selfPtr = nullptr; | |
560 | |
561 Maybe<Own<Event>> fire() override; | |
562 }; | |
563 | |
564 template <typename T> | |
565 Own<PromiseNode> maybeChain(Own<PromiseNode>&& node, Promise<T>*) { | |
566 return heap<ChainPromiseNode>(kj::mv(node)); | |
567 } | |
568 | |
569 template <typename T> | |
570 Own<PromiseNode>&& maybeChain(Own<PromiseNode>&& node, T*) { | |
571 return kj::mv(node); | |
572 } | |
573 | |
574 // ------------------------------------------------------------------- | |
575 | |
576 class ExclusiveJoinPromiseNode final: public PromiseNode { | |
577 public: | |
578 ExclusiveJoinPromiseNode(Own<PromiseNode> left, Own<PromiseNode> right); | |
579 ~ExclusiveJoinPromiseNode() noexcept(false); | |
580 | |
581 void onReady(Event& event) noexcept override; | |
582 void get(ExceptionOrValue& output) noexcept override; | |
583 PromiseNode* getInnerForTrace() override; | |
584 | |
585 private: | |
586 class Branch: public Event { | |
587 public: | |
588 Branch(ExclusiveJoinPromiseNode& joinNode, Own<PromiseNode> dependency); | |
589 ~Branch() noexcept(false); | |
590 | |
591 bool get(ExceptionOrValue& output); | |
592 // Returns true if this is the side that finished. | |
593 | |
594 Maybe<Own<Event>> fire() override; | |
595 _::PromiseNode* getInnerForTrace() override; | |
596 | |
597 private: | |
598 ExclusiveJoinPromiseNode& joinNode; | |
599 Own<PromiseNode> dependency; | |
600 }; | |
601 | |
602 Branch left; | |
603 Branch right; | |
604 OnReadyEvent onReadyEvent; | |
605 }; | |
606 | |
607 // ------------------------------------------------------------------- | |
608 | |
609 class ArrayJoinPromiseNodeBase: public PromiseNode { | |
610 public: | |
611 ArrayJoinPromiseNodeBase(Array<Own<PromiseNode>> promises, | |
612 ExceptionOrValue* resultParts, size_t partSize); | |
613 ~ArrayJoinPromiseNodeBase() noexcept(false); | |
614 | |
615 void onReady(Event& event) noexcept override final; | |
616 void get(ExceptionOrValue& output) noexcept override final; | |
617 PromiseNode* getInnerForTrace() override final; | |
618 | |
619 protected: | |
620 virtual void getNoError(ExceptionOrValue& output) noexcept = 0; | |
621 // Called to compile the result only in the case where there were no errors. | |
622 | |
623 private: | |
624 uint countLeft; | |
625 OnReadyEvent onReadyEvent; | |
626 | |
627 class Branch final: public Event { | |
628 public: | |
629 Branch(ArrayJoinPromiseNodeBase& joinNode, Own<PromiseNode> dependency, | |
630 ExceptionOrValue& output); | |
631 ~Branch() noexcept(false); | |
632 | |
633 Maybe<Own<Event>> fire() override; | |
634 _::PromiseNode* getInnerForTrace() override; | |
635 | |
636 Maybe<Exception> getPart(); | |
637 // Calls dependency->get(output). If there was an exception, return it. | |
638 | |
639 private: | |
640 ArrayJoinPromiseNodeBase& joinNode; | |
641 Own<PromiseNode> dependency; | |
642 ExceptionOrValue& output; | |
643 }; | |
644 | |
645 Array<Branch> branches; | |
646 }; | |
647 | |
648 template <typename T> | |
649 class ArrayJoinPromiseNode final: public ArrayJoinPromiseNodeBase { | |
650 public: | |
651 ArrayJoinPromiseNode(Array<Own<PromiseNode>> promises, | |
652 Array<ExceptionOr<T>> resultParts) | |
653 : ArrayJoinPromiseNodeBase(kj::mv(promises), resultParts.begin(), sizeof(ExceptionOr<T>)), | |
654 resultParts(kj::mv(resultParts)) {} | |
655 | |
656 protected: | |
657 void getNoError(ExceptionOrValue& output) noexcept override { | |
658 auto builder = heapArrayBuilder<T>(resultParts.size()); | |
659 for (auto& part: resultParts) { | |
660 KJ_IASSERT(part.value != nullptr, | |
661 "Bug in KJ promise framework: Promise result had neither value no exception."); | |
662 builder.add(kj::mv(*_::readMaybe(part.value))); | |
663 } | |
664 output.as<Array<T>>() = builder.finish(); | |
665 } | |
666 | |
667 private: | |
668 Array<ExceptionOr<T>> resultParts; | |
669 }; | |
670 | |
671 template <> | |
672 class ArrayJoinPromiseNode<void> final: public ArrayJoinPromiseNodeBase { | |
673 public: | |
674 ArrayJoinPromiseNode(Array<Own<PromiseNode>> promises, | |
675 Array<ExceptionOr<_::Void>> resultParts); | |
676 ~ArrayJoinPromiseNode(); | |
677 | |
678 protected: | |
679 void getNoError(ExceptionOrValue& output) noexcept override; | |
680 | |
681 private: | |
682 Array<ExceptionOr<_::Void>> resultParts; | |
683 }; | |
684 | |
685 // ------------------------------------------------------------------- | |
686 | |
687 class EagerPromiseNodeBase: public PromiseNode, protected Event { | |
688 // A PromiseNode that eagerly evaluates its dependency even if its dependent does not eagerly | |
689 // evaluate it. | |
690 | |
691 public: | |
692 EagerPromiseNodeBase(Own<PromiseNode>&& dependency, ExceptionOrValue& resultRef); | |
693 | |
694 void onReady(Event& event) noexcept override; | |
695 PromiseNode* getInnerForTrace() override; | |
696 | |
697 private: | |
698 Own<PromiseNode> dependency; | |
699 OnReadyEvent onReadyEvent; | |
700 | |
701 ExceptionOrValue& resultRef; | |
702 | |
703 Maybe<Own<Event>> fire() override; | |
704 }; | |
705 | |
706 template <typename T> | |
707 class EagerPromiseNode final: public EagerPromiseNodeBase { | |
708 public: | |
709 EagerPromiseNode(Own<PromiseNode>&& dependency) | |
710 : EagerPromiseNodeBase(kj::mv(dependency), result) {} | |
711 | |
712 void get(ExceptionOrValue& output) noexcept override { | |
713 output.as<T>() = kj::mv(result); | |
714 } | |
715 | |
716 private: | |
717 ExceptionOr<T> result; | |
718 }; | |
719 | |
720 template <typename T> | |
721 Own<PromiseNode> spark(Own<PromiseNode>&& node) { | |
722 // Forces evaluation of the given node to begin as soon as possible, even if no one is waiting | |
723 // on it. | |
724 return heap<EagerPromiseNode<T>>(kj::mv(node)); | |
725 } | |
726 | |
727 // ------------------------------------------------------------------- | |
728 | |
729 class AdapterPromiseNodeBase: public PromiseNode { | |
730 public: | |
731 void onReady(Event& event) noexcept override; | |
732 | |
733 protected: | |
734 inline void setReady() { | |
735 onReadyEvent.arm(); | |
736 } | |
737 | |
738 private: | |
739 OnReadyEvent onReadyEvent; | |
740 }; | |
741 | |
742 template <typename T, typename Adapter> | |
743 class AdapterPromiseNode final: public AdapterPromiseNodeBase, | |
744 private PromiseFulfiller<UnfixVoid<T>> { | |
745 // A PromiseNode that wraps a PromiseAdapter. | |
746 | |
747 public: | |
748 template <typename... Params> | |
749 AdapterPromiseNode(Params&&... params) | |
750 : adapter(static_cast<PromiseFulfiller<UnfixVoid<T>>&>(*this), kj::fwd<Params>(params)...) {} | |
751 | |
752 void get(ExceptionOrValue& output) noexcept override { | |
753 KJ_IREQUIRE(!isWaiting()); | |
754 output.as<T>() = kj::mv(result); | |
755 } | |
756 | |
757 private: | |
758 ExceptionOr<T> result; | |
759 bool waiting = true; | |
760 Adapter adapter; | |
761 | |
762 void fulfill(T&& value) override { | |
763 if (waiting) { | |
764 waiting = false; | |
765 result = ExceptionOr<T>(kj::mv(value)); | |
766 setReady(); | |
767 } | |
768 } | |
769 | |
770 void reject(Exception&& exception) override { | |
771 if (waiting) { | |
772 waiting = false; | |
773 result = ExceptionOr<T>(false, kj::mv(exception)); | |
774 setReady(); | |
775 } | |
776 } | |
777 | |
778 bool isWaiting() override { | |
779 return waiting; | |
780 } | |
781 }; | |
782 | |
783 } // namespace _ (private) | |
784 | |
785 // ======================================================================================= | |
786 | |
787 template <typename T> | |
788 Promise<T>::Promise(_::FixVoid<T> value) | |
789 : PromiseBase(heap<_::ImmediatePromiseNode<_::FixVoid<T>>>(kj::mv(value))) {} | |
790 | |
791 template <typename T> | |
792 Promise<T>::Promise(kj::Exception&& exception) | |
793 : PromiseBase(heap<_::ImmediateBrokenPromiseNode>(kj::mv(exception))) {} | |
794 | |
795 template <typename T> | |
796 template <typename Func, typename ErrorFunc> | |
797 PromiseForResult<Func, T> Promise<T>::then(Func&& func, ErrorFunc&& errorHandler) { | |
798 typedef _::FixVoid<_::ReturnType<Func, T>> ResultT; | |
799 | |
800 Own<_::PromiseNode> intermediate = | |
801 heap<_::TransformPromiseNode<ResultT, _::FixVoid<T>, Func, ErrorFunc>>( | |
802 kj::mv(node), kj::fwd<Func>(func), kj::fwd<ErrorFunc>(errorHandler)); | |
803 return PromiseForResult<Func, T>(false, | |
804 _::maybeChain(kj::mv(intermediate), implicitCast<ResultT*>(nullptr))); | |
805 } | |
806 | |
807 namespace _ { // private | |
808 | |
809 template <typename T> | |
810 struct IdentityFunc { | |
811 inline T operator()(T&& value) const { | |
812 return kj::mv(value); | |
813 } | |
814 }; | |
815 template <typename T> | |
816 struct IdentityFunc<Promise<T>> { | |
817 inline Promise<T> operator()(T&& value) const { | |
818 return kj::mv(value); | |
819 } | |
820 }; | |
821 template <> | |
822 struct IdentityFunc<void> { | |
823 inline void operator()() const {} | |
824 }; | |
825 template <> | |
826 struct IdentityFunc<Promise<void>> { | |
827 Promise<void> operator()() const; | |
828 // This can't be inline because it will make the translation unit depend on kj-async. Awkwardly, | |
829 // Cap'n Proto relies on being able to include this header without creating such a link-time | |
830 // dependency. | |
831 }; | |
832 | |
833 } // namespace _ (private) | |
834 | |
835 template <typename T> | |
836 template <typename ErrorFunc> | |
837 Promise<T> Promise<T>::catch_(ErrorFunc&& errorHandler) { | |
838 // then()'s ErrorFunc can only return a Promise if Func also returns a Promise. In this case, | |
839 // Func is being filled in automatically. We want to make sure ErrorFunc can return a Promise, | |
840 // but we don't want the extra overhead of promise chaining if ErrorFunc doesn't actually | |
841 // return a promise. So we make our Func return match ErrorFunc. | |
842 return then(_::IdentityFunc<decltype(errorHandler(instance<Exception&&>()))>(), | |
843 kj::fwd<ErrorFunc>(errorHandler)); | |
844 } | |
845 | |
846 template <typename T> | |
847 T Promise<T>::wait(WaitScope& waitScope) { | |
848 _::ExceptionOr<_::FixVoid<T>> result; | |
849 | |
850 waitImpl(kj::mv(node), result, waitScope); | |
851 | |
852 KJ_IF_MAYBE(value, result.value) { | |
853 KJ_IF_MAYBE(exception, result.exception) { | |
854 throwRecoverableException(kj::mv(*exception)); | |
855 } | |
856 return _::returnMaybeVoid(kj::mv(*value)); | |
857 } else KJ_IF_MAYBE(exception, result.exception) { | |
858 throwFatalException(kj::mv(*exception)); | |
859 } else { | |
860 // Result contained neither a value nor an exception? | |
861 KJ_UNREACHABLE; | |
862 } | |
863 } | |
864 | |
865 template <typename T> | |
866 ForkedPromise<T> Promise<T>::fork() { | |
867 return ForkedPromise<T>(false, refcounted<_::ForkHub<_::FixVoid<T>>>(kj::mv(node))); | |
868 } | |
869 | |
870 template <typename T> | |
871 Promise<T> ForkedPromise<T>::addBranch() { | |
872 return hub->addBranch(); | |
873 } | |
874 | |
875 template <typename T> | |
876 _::SplitTuplePromise<T> Promise<T>::split() { | |
877 return refcounted<_::ForkHub<_::FixVoid<T>>>(kj::mv(node))->split(); | |
878 } | |
879 | |
880 template <typename T> | |
881 Promise<T> Promise<T>::exclusiveJoin(Promise<T>&& other) { | |
882 return Promise(false, heap<_::ExclusiveJoinPromiseNode>(kj::mv(node), kj::mv(other.node))); | |
883 } | |
884 | |
885 template <typename T> | |
886 template <typename... Attachments> | |
887 Promise<T> Promise<T>::attach(Attachments&&... attachments) { | |
888 return Promise(false, kj::heap<_::AttachmentPromiseNode<Tuple<Attachments...>>>( | |
889 kj::mv(node), kj::tuple(kj::fwd<Attachments>(attachments)...))); | |
890 } | |
891 | |
892 template <typename T> | |
893 template <typename ErrorFunc> | |
894 Promise<T> Promise<T>::eagerlyEvaluate(ErrorFunc&& errorHandler) { | |
895 // See catch_() for commentary. | |
896 return Promise(false, _::spark<_::FixVoid<T>>(then( | |
897 _::IdentityFunc<decltype(errorHandler(instance<Exception&&>()))>(), | |
898 kj::fwd<ErrorFunc>(errorHandler)).node)); | |
899 } | |
900 | |
901 template <typename T> | |
902 Promise<T> Promise<T>::eagerlyEvaluate(decltype(nullptr)) { | |
903 return Promise(false, _::spark<_::FixVoid<T>>(kj::mv(node))); | |
904 } | |
905 | |
906 template <typename T> | |
907 kj::String Promise<T>::trace() { | |
908 return PromiseBase::trace(); | |
909 } | |
910 | |
911 template <typename Func> | |
912 inline PromiseForResult<Func, void> evalLater(Func&& func) { | |
913 return _::yield().then(kj::fwd<Func>(func), _::PropagateException()); | |
914 } | |
915 | |
916 template <typename Func> | |
917 inline PromiseForResult<Func, void> evalNow(Func&& func) { | |
918 PromiseForResult<Func, void> result = nullptr; | |
919 KJ_IF_MAYBE(e, kj::runCatchingExceptions([&]() { | |
920 result = func(); | |
921 })) { | |
922 result = kj::mv(*e); | |
923 } | |
924 return result; | |
925 } | |
926 | |
927 template <typename T> | |
928 template <typename ErrorFunc> | |
929 void Promise<T>::detach(ErrorFunc&& errorHandler) { | |
930 return _::detach(then([](T&&) {}, kj::fwd<ErrorFunc>(errorHandler))); | |
931 } | |
932 | |
933 template <> | |
934 template <typename ErrorFunc> | |
935 void Promise<void>::detach(ErrorFunc&& errorHandler) { | |
936 return _::detach(then([]() {}, kj::fwd<ErrorFunc>(errorHandler))); | |
937 } | |
938 | |
939 template <typename T> | |
940 Promise<Array<T>> joinPromises(Array<Promise<T>>&& promises) { | |
941 return Promise<Array<T>>(false, kj::heap<_::ArrayJoinPromiseNode<T>>( | |
942 KJ_MAP(p, promises) { return kj::mv(p.node); }, | |
943 heapArray<_::ExceptionOr<T>>(promises.size()))); | |
944 } | |
945 | |
946 // ======================================================================================= | |
947 | |
948 namespace _ { // private | |
949 | |
950 template <typename T> | |
951 class WeakFulfiller final: public PromiseFulfiller<T>, private kj::Disposer { | |
952 // A wrapper around PromiseFulfiller which can be detached. | |
953 // | |
954 // There are a couple non-trivialities here: | |
955 // - If the WeakFulfiller is discarded, we want the promise it fulfills to be implicitly | |
956 // rejected. | |
957 // - We cannot destroy the WeakFulfiller until the application has discarded it *and* it has been | |
958 // detached from the underlying fulfiller, because otherwise the later detach() call will go | |
959 // to a dangling pointer. Essentially, WeakFulfiller is reference counted, although the | |
960 // refcount never goes over 2 and we manually implement the refcounting because we need to do | |
961 // other special things when each side detaches anyway. To this end, WeakFulfiller is its own | |
962 // Disposer -- dispose() is called when the application discards its owned pointer to the | |
963 // fulfiller and detach() is called when the promise is destroyed. | |
964 | |
965 public: | |
966 KJ_DISALLOW_COPY(WeakFulfiller); | |
967 | |
968 static kj::Own<WeakFulfiller> make() { | |
969 WeakFulfiller* ptr = new WeakFulfiller; | |
970 return Own<WeakFulfiller>(ptr, *ptr); | |
971 } | |
972 | |
973 void fulfill(FixVoid<T>&& value) override { | |
974 if (inner != nullptr) { | |
975 inner->fulfill(kj::mv(value)); | |
976 } | |
977 } | |
978 | |
979 void reject(Exception&& exception) override { | |
980 if (inner != nullptr) { | |
981 inner->reject(kj::mv(exception)); | |
982 } | |
983 } | |
984 | |
985 bool isWaiting() override { | |
986 return inner != nullptr && inner->isWaiting(); | |
987 } | |
988 | |
989 void attach(PromiseFulfiller<T>& newInner) { | |
990 inner = &newInner; | |
991 } | |
992 | |
993 void detach(PromiseFulfiller<T>& from) { | |
994 if (inner == nullptr) { | |
995 // Already disposed. | |
996 delete this; | |
997 } else { | |
998 KJ_IREQUIRE(inner == &from); | |
999 inner = nullptr; | |
1000 } | |
1001 } | |
1002 | |
1003 private: | |
1004 mutable PromiseFulfiller<T>* inner; | |
1005 | |
1006 WeakFulfiller(): inner(nullptr) {} | |
1007 | |
1008 void disposeImpl(void* pointer) const override { | |
1009 // TODO(perf): Factor some of this out so it isn't regenerated for every fulfiller type? | |
1010 | |
1011 if (inner == nullptr) { | |
1012 // Already detached. | |
1013 delete this; | |
1014 } else { | |
1015 if (inner->isWaiting()) { | |
1016 inner->reject(kj::Exception(kj::Exception::Type::FAILED, __FILE__, __LINE__, | |
1017 kj::heapString("PromiseFulfiller was destroyed without fulfilling the promise."))); | |
1018 } | |
1019 inner = nullptr; | |
1020 } | |
1021 } | |
1022 }; | |
1023 | |
1024 template <typename T> | |
1025 class PromiseAndFulfillerAdapter { | |
1026 public: | |
1027 PromiseAndFulfillerAdapter(PromiseFulfiller<T>& fulfiller, | |
1028 WeakFulfiller<T>& wrapper) | |
1029 : fulfiller(fulfiller), wrapper(wrapper) { | |
1030 wrapper.attach(fulfiller); | |
1031 } | |
1032 | |
1033 ~PromiseAndFulfillerAdapter() noexcept(false) { | |
1034 wrapper.detach(fulfiller); | |
1035 } | |
1036 | |
1037 private: | |
1038 PromiseFulfiller<T>& fulfiller; | |
1039 WeakFulfiller<T>& wrapper; | |
1040 }; | |
1041 | |
1042 } // namespace _ (private) | |
1043 | |
1044 template <typename T> | |
1045 template <typename Func> | |
1046 bool PromiseFulfiller<T>::rejectIfThrows(Func&& func) { | |
1047 KJ_IF_MAYBE(exception, kj::runCatchingExceptions(kj::mv(func))) { | |
1048 reject(kj::mv(*exception)); | |
1049 return false; | |
1050 } else { | |
1051 return true; | |
1052 } | |
1053 } | |
1054 | |
1055 template <typename Func> | |
1056 bool PromiseFulfiller<void>::rejectIfThrows(Func&& func) { | |
1057 KJ_IF_MAYBE(exception, kj::runCatchingExceptions(kj::mv(func))) { | |
1058 reject(kj::mv(*exception)); | |
1059 return false; | |
1060 } else { | |
1061 return true; | |
1062 } | |
1063 } | |
1064 | |
1065 template <typename T, typename Adapter, typename... Params> | |
1066 Promise<T> newAdaptedPromise(Params&&... adapterConstructorParams) { | |
1067 return Promise<T>(false, heap<_::AdapterPromiseNode<_::FixVoid<T>, Adapter>>( | |
1068 kj::fwd<Params>(adapterConstructorParams)...)); | |
1069 } | |
1070 | |
1071 template <typename T> | |
1072 PromiseFulfillerPair<T> newPromiseAndFulfiller() { | |
1073 auto wrapper = _::WeakFulfiller<T>::make(); | |
1074 | |
1075 Own<_::PromiseNode> intermediate( | |
1076 heap<_::AdapterPromiseNode<_::FixVoid<T>, _::PromiseAndFulfillerAdapter<T>>>(*wrapper)); | |
1077 Promise<_::JoinPromises<T>> promise(false, | |
1078 _::maybeChain(kj::mv(intermediate), implicitCast<T*>(nullptr))); | |
1079 | |
1080 return PromiseFulfillerPair<T> { kj::mv(promise), kj::mv(wrapper) }; | |
1081 } | |
1082 | |
1083 } // namespace kj | |
1084 | |
1085 #endif // KJ_ASYNC_INL_H_ |