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_