You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					1113 lines
				
				34 KiB
			
		
		
			
		
	
	
					1113 lines
				
				34 KiB
			| 
								 
											6 years ago
										 
									 | 
							
								// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
							 | 
						||
| 
								 | 
							
								// Licensed under the MIT License:
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// Permission is hereby granted, free of charge, to any person obtaining a copy
							 | 
						||
| 
								 | 
							
								// of this software and associated documentation files (the "Software"), to deal
							 | 
						||
| 
								 | 
							
								// in the Software without restriction, including without limitation the rights
							 | 
						||
| 
								 | 
							
								// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
							 | 
						||
| 
								 | 
							
								// copies of the Software, and to permit persons to whom the Software is
							 | 
						||
| 
								 | 
							
								// furnished to do so, subject to the following conditions:
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// The above copyright notice and this permission notice shall be included in
							 | 
						||
| 
								 | 
							
								// all copies or substantial portions of the Software.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
							 | 
						||
| 
								 | 
							
								// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
							 | 
						||
| 
								 | 
							
								// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
							 | 
						||
| 
								 | 
							
								// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
							 | 
						||
| 
								 | 
							
								// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
							 | 
						||
| 
								 | 
							
								// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
							 | 
						||
| 
								 | 
							
								// THE SOFTWARE.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// This file contains extended inline implementation details that are required along with async.h.
							 | 
						||
| 
								 | 
							
								// We move this all into a separate file to make async.h more readable.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// Non-inline declarations here are defined in async.c++.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef KJ_ASYNC_H_
							 | 
						||
| 
								 | 
							
								#error "Do not include this directly; include kj/async.h."
							 | 
						||
| 
								 | 
							
								#include "async.h"  // help IDE parse this file
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef KJ_ASYNC_INL_H_
							 | 
						||
| 
								 | 
							
								#define KJ_ASYNC_INL_H_
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if defined(__GNUC__) && !KJ_HEADER_WARNINGS
							 | 
						||
| 
								 | 
							
								#pragma GCC system_header
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace kj {
							 | 
						||
| 
								 | 
							
								namespace _ {  // private
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename T>
							 | 
						||
| 
								 | 
							
								class ExceptionOr;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class ExceptionOrValue {
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  ExceptionOrValue(bool, Exception&& exception): exception(kj::mv(exception)) {}
							 | 
						||
| 
								 | 
							
								  KJ_DISALLOW_COPY(ExceptionOrValue);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  void addException(Exception&& exception) {
							 | 
						||
| 
								 | 
							
								    if (this->exception == nullptr) {
							 | 
						||
| 
								 | 
							
								      this->exception = kj::mv(exception);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  template <typename T>
							 | 
						||
| 
								 | 
							
								  ExceptionOr<T>& as() { return *static_cast<ExceptionOr<T>*>(this); }
							 | 
						||
| 
								 | 
							
								  template <typename T>
							 | 
						||
| 
								 | 
							
								  const ExceptionOr<T>& as() const { return *static_cast<const ExceptionOr<T>*>(this); }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Maybe<Exception> exception;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								protected:
							 | 
						||
| 
								 | 
							
								  // Allow subclasses to have move constructor / assignment.
							 | 
						||
| 
								 | 
							
								  ExceptionOrValue() = default;
							 | 
						||
| 
								 | 
							
								  ExceptionOrValue(ExceptionOrValue&& other) = default;
							 | 
						||
| 
								 | 
							
								  ExceptionOrValue& operator=(ExceptionOrValue&& other) = default;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename T>
							 | 
						||
| 
								 | 
							
								class ExceptionOr: public ExceptionOrValue {
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  ExceptionOr() = default;
							 | 
						||
| 
								 | 
							
								  ExceptionOr(T&& value): value(kj::mv(value)) {}
							 | 
						||
| 
								 | 
							
								  ExceptionOr(bool, Exception&& exception): ExceptionOrValue(false, kj::mv(exception)) {}
							 | 
						||
| 
								 | 
							
								  ExceptionOr(ExceptionOr&&) = default;
							 | 
						||
| 
								 | 
							
								  ExceptionOr& operator=(ExceptionOr&&) = default;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Maybe<T> value;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class Event {
							 | 
						||
| 
								 | 
							
								  // An event waiting to be executed.  Not for direct use by applications -- promises use this
							 | 
						||
| 
								 | 
							
								  // internally.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  Event();
							 | 
						||
| 
								 | 
							
								  ~Event() noexcept(false);
							 | 
						||
| 
								 | 
							
								  KJ_DISALLOW_COPY(Event);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  void armDepthFirst();
							 | 
						||
| 
								 | 
							
								  // Enqueue this event so that `fire()` will be called from the event loop soon.
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // Events scheduled in this way are executed in depth-first order:  if an event callback arms
							 | 
						||
| 
								 | 
							
								  // more events, those events are placed at the front of the queue (in the order in which they
							 | 
						||
| 
								 | 
							
								  // were armed), so that they run immediately after the first event's callback returns.
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // Depth-first event scheduling is appropriate for events that represent simple continuations
							 | 
						||
| 
								 | 
							
								  // of a previous event that should be globbed together for performance.  Depth-first scheduling
							 | 
						||
| 
								 | 
							
								  // can lead to starvation, so any long-running task must occasionally yield with
							 | 
						||
| 
								 | 
							
								  // `armBreadthFirst()`.  (Promise::then() uses depth-first whereas evalLater() uses
							 | 
						||
| 
								 | 
							
								  // breadth-first.)
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // To use breadth-first scheduling instead, use `armBreadthFirst()`.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  void armBreadthFirst();
							 | 
						||
| 
								 | 
							
								  // Like `armDepthFirst()` except that the event is placed at the end of the queue.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  kj::String trace();
							 | 
						||
| 
								 | 
							
								  // Dump debug info about this event.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  virtual _::PromiseNode* getInnerForTrace();
							 | 
						||
| 
								 | 
							
								  // If this event wraps a PromiseNode, get that node.  Used for debug tracing.
							 | 
						||
| 
								 | 
							
								  // Default implementation returns nullptr.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								protected:
							 | 
						||
| 
								 | 
							
								  virtual Maybe<Own<Event>> fire() = 0;
							 | 
						||
| 
								 | 
							
								  // Fire the event.  Possibly returns a pointer to itself, which will be discarded by the
							 | 
						||
| 
								 | 
							
								  // caller.  This is the only way that an event can delete itself as a result of firing, as
							 | 
						||
| 
								 | 
							
								  // doing so from within fire() will throw an exception.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								  friend class kj::EventLoop;
							 | 
						||
| 
								 | 
							
								  EventLoop& loop;
							 | 
						||
| 
								 | 
							
								  Event* next;
							 | 
						||
| 
								 | 
							
								  Event** prev;
							 | 
						||
| 
								 | 
							
								  bool firing = false;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class PromiseNode {
							 | 
						||
| 
								 | 
							
								  // A Promise<T> contains a chain of PromiseNodes tracking the pending transformations.
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // To reduce generated code bloat, PromiseNode is not a template.  Instead, it makes very hacky
							 | 
						||
| 
								 | 
							
								  // use of pointers to ExceptionOrValue which actually point to ExceptionOr<T>, but are only
							 | 
						||
| 
								 | 
							
								  // so down-cast in the few places that really need to be templated.  Luckily this is all
							 | 
						||
| 
								 | 
							
								  // internal implementation details.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  virtual void onReady(Event& event) noexcept = 0;
							 | 
						||
| 
								 | 
							
								  // Arms the given event when ready.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  virtual void setSelfPointer(Own<PromiseNode>* selfPtr) noexcept;
							 | 
						||
| 
								 | 
							
								  // Tells the node that `selfPtr` is the pointer that owns this node, and will continue to own
							 | 
						||
| 
								 | 
							
								  // this node until it is destroyed or setSelfPointer() is called again.  ChainPromiseNode uses
							 | 
						||
| 
								 | 
							
								  // this to shorten redundant chains.  The default implementation does nothing; only
							 | 
						||
| 
								 | 
							
								  // ChainPromiseNode should implement this.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  virtual void get(ExceptionOrValue& output) noexcept = 0;
							 | 
						||
| 
								 | 
							
								  // Get the result.  `output` points to an ExceptionOr<T> into which the result will be written.
							 | 
						||
| 
								 | 
							
								  // Can only be called once, and only after the node is ready.  Must be called directly from the
							 | 
						||
| 
								 | 
							
								  // event loop, with no application code on the stack.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  virtual PromiseNode* getInnerForTrace();
							 | 
						||
| 
								 | 
							
								  // If this node wraps some other PromiseNode, get the wrapped node.  Used for debug tracing.
							 | 
						||
| 
								 | 
							
								  // Default implementation returns nullptr.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								protected:
							 | 
						||
| 
								 | 
							
								  class OnReadyEvent {
							 | 
						||
| 
								 | 
							
								    // Helper class for implementing onReady().
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  public:
							 | 
						||
| 
								 | 
							
								    void init(Event& newEvent);
							 | 
						||
| 
								 | 
							
								    // Returns true if arm() was already called.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    void arm();
							 | 
						||
| 
								 | 
							
								    // Arms the event if init() has already been called and makes future calls to init() return
							 | 
						||
| 
								 | 
							
								    // true.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  private:
							 | 
						||
| 
								 | 
							
								    Event* event = nullptr;
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// -------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class ImmediatePromiseNodeBase: public PromiseNode {
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  ImmediatePromiseNodeBase();
							 | 
						||
| 
								 | 
							
								  ~ImmediatePromiseNodeBase() noexcept(false);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  void onReady(Event& event) noexcept override;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename T>
							 | 
						||
| 
								 | 
							
								class ImmediatePromiseNode final: public ImmediatePromiseNodeBase {
							 | 
						||
| 
								 | 
							
								  // A promise that has already been resolved to an immediate value or exception.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  ImmediatePromiseNode(ExceptionOr<T>&& result): result(kj::mv(result)) {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  void get(ExceptionOrValue& output) noexcept override {
							 | 
						||
| 
								 | 
							
								    output.as<T>() = kj::mv(result);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								  ExceptionOr<T> result;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class ImmediateBrokenPromiseNode final: public ImmediatePromiseNodeBase {
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  ImmediateBrokenPromiseNode(Exception&& exception);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  void get(ExceptionOrValue& output) noexcept override;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								  Exception exception;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// -------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class AttachmentPromiseNodeBase: public PromiseNode {
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  AttachmentPromiseNodeBase(Own<PromiseNode>&& dependency);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  void onReady(Event& event) noexcept override;
							 | 
						||
| 
								 | 
							
								  void get(ExceptionOrValue& output) noexcept override;
							 | 
						||
| 
								 | 
							
								  PromiseNode* getInnerForTrace() override;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								  Own<PromiseNode> dependency;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  void dropDependency();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  template <typename>
							 | 
						||
| 
								 | 
							
								  friend class AttachmentPromiseNode;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename Attachment>
							 | 
						||
| 
								 | 
							
								class AttachmentPromiseNode final: public AttachmentPromiseNodeBase {
							 | 
						||
| 
								 | 
							
								  // A PromiseNode that holds on to some object (usually, an Own<T>, but could be any movable
							 | 
						||
| 
								 | 
							
								  // object) until the promise resolves.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  AttachmentPromiseNode(Own<PromiseNode>&& dependency, Attachment&& attachment)
							 | 
						||
| 
								 | 
							
								      : AttachmentPromiseNodeBase(kj::mv(dependency)),
							 | 
						||
| 
								 | 
							
								        attachment(kj::mv<Attachment>(attachment)) {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  ~AttachmentPromiseNode() noexcept(false) {
							 | 
						||
| 
								 | 
							
								    // We need to make sure the dependency is deleted before we delete the attachment because the
							 | 
						||
| 
								 | 
							
								    // dependency may be using the attachment.
							 | 
						||
| 
								 | 
							
								    dropDependency();
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								  Attachment attachment;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// -------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class PtmfHelper {
							 | 
						||
| 
								 | 
							
								  // This class is a private helper for GetFunctorStartAddress. The class represents the internal
							 | 
						||
| 
								 | 
							
								  // representation of a pointer-to-member-function.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  template <typename... ParamTypes>
							 | 
						||
| 
								 | 
							
								  friend struct GetFunctorStartAddress;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if __GNUG__
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  void* ptr;
							 | 
						||
| 
								 | 
							
								  ptrdiff_t adj;
							 | 
						||
| 
								 | 
							
								  // Layout of a pointer-to-member-function used by GCC and compatible compilers.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  void* apply(void* obj) {
							 | 
						||
| 
								 | 
							
								#if defined(__arm__) || defined(__mips__) || defined(__aarch64__)
							 | 
						||
| 
								 | 
							
								    if (adj & 1) {
							 | 
						||
| 
								 | 
							
								      ptrdiff_t voff = (ptrdiff_t)ptr;
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								    ptrdiff_t voff = (ptrdiff_t)ptr;
							 | 
						||
| 
								 | 
							
								    if (voff & 1) {
							 | 
						||
| 
								 | 
							
								      voff &= ~1;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								      return *(void**)(*(char**)obj + voff);
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								      return ptr;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define BODY \
							 | 
						||
| 
								 | 
							
								    PtmfHelper result; \
							 | 
						||
| 
								 | 
							
								    static_assert(sizeof(p) == sizeof(result), "unknown ptmf layout"); \
							 | 
						||
| 
								 | 
							
								    memcpy(&result, &p, sizeof(result)); \
							 | 
						||
| 
								 | 
							
								    return result
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#else  // __GNUG__
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  void* apply(void* obj) { return nullptr; }
							 | 
						||
| 
								 | 
							
								  // TODO(port):  PTMF instruction address extraction
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define BODY return PtmfHelper{}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif  // __GNUG__, else
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  template <typename R, typename C, typename... P, typename F>
							 | 
						||
| 
								 | 
							
								  static PtmfHelper from(F p) { BODY; }
							 | 
						||
| 
								 | 
							
								  // Create a PtmfHelper from some arbitrary pointer-to-member-function which is not
							 | 
						||
| 
								 | 
							
								  // overloaded nor a template. In this case the compiler is able to deduce the full function
							 | 
						||
| 
								 | 
							
								  // signature directly given the name since there is only one function with that name.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  template <typename R, typename C, typename... P>
							 | 
						||
| 
								 | 
							
								  static PtmfHelper from(R (C::*p)(NoInfer<P>...)) { BODY; }
							 | 
						||
| 
								 | 
							
								  template <typename R, typename C, typename... P>
							 | 
						||
| 
								 | 
							
								  static PtmfHelper from(R (C::*p)(NoInfer<P>...) const) { BODY; }
							 | 
						||
| 
								 | 
							
								  // Create a PtmfHelper from some poniter-to-member-function which is a template. In this case
							 | 
						||
| 
								 | 
							
								  // the function must match exactly the containing type C, return type R, and parameter types P...
							 | 
						||
| 
								 | 
							
								  // GetFunctorStartAddress normally specifies exactly the correct C and R, but can only make a
							 | 
						||
| 
								 | 
							
								  // guess at P. Luckily, if the function parameters are template parameters then it's not
							 | 
						||
| 
								 | 
							
								  // necessary to be precise about P.
							 | 
						||
| 
								 | 
							
								#undef BODY
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename... ParamTypes>
							 | 
						||
| 
								 | 
							
								struct GetFunctorStartAddress {
							 | 
						||
| 
								 | 
							
								  // Given a functor (any object defining operator()), return the start address of the function,
							 | 
						||
| 
								 | 
							
								  // suitable for passing to addr2line to obtain a source file/line for debugging purposes.
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // This turns out to be incredibly hard to implement in the presence of overloaded or templated
							 | 
						||
| 
								 | 
							
								  // functors. Therefore, we impose these specific restrictions, specific to our use case:
							 | 
						||
| 
								 | 
							
								  // - Overloading is not allowed, but templating is. (Generally we only intend to support lambdas
							 | 
						||
| 
								 | 
							
								  //   anyway.)
							 | 
						||
| 
								 | 
							
								  // - The template parameters to GetFunctorStartAddress specify a hint as to the expected
							 | 
						||
| 
								 | 
							
								  //   parameter types. If the functor is templated, its parameters must match exactly these types.
							 | 
						||
| 
								 | 
							
								  //   (If it's not templated, ParamTypes are ignored.)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  template <typename Func>
							 | 
						||
| 
								 | 
							
								  static void* apply(Func&& func) {
							 | 
						||
| 
								 | 
							
								    typedef decltype(func(instance<ParamTypes>()...)) ReturnType;
							 | 
						||
| 
								 | 
							
								    return PtmfHelper::from<ReturnType, Decay<Func>, ParamTypes...>(
							 | 
						||
| 
								 | 
							
								        &Decay<Func>::operator()).apply(&func);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <>
							 | 
						||
| 
								 | 
							
								struct GetFunctorStartAddress<Void&&>: public GetFunctorStartAddress<> {};
							 | 
						||
| 
								 | 
							
								// Hack for TransformPromiseNode use case: an input type of `Void` indicates that the function
							 | 
						||
| 
								 | 
							
								// actually has no parameters.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class TransformPromiseNodeBase: public PromiseNode {
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  TransformPromiseNodeBase(Own<PromiseNode>&& dependency, void* continuationTracePtr);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  void onReady(Event& event) noexcept override;
							 | 
						||
| 
								 | 
							
								  void get(ExceptionOrValue& output) noexcept override;
							 | 
						||
| 
								 | 
							
								  PromiseNode* getInnerForTrace() override;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								  Own<PromiseNode> dependency;
							 | 
						||
| 
								 | 
							
								  void* continuationTracePtr;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  void dropDependency();
							 | 
						||
| 
								 | 
							
								  void getDepResult(ExceptionOrValue& output);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  virtual void getImpl(ExceptionOrValue& output) = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  template <typename, typename, typename, typename>
							 | 
						||
| 
								 | 
							
								  friend class TransformPromiseNode;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename T, typename DepT, typename Func, typename ErrorFunc>
							 | 
						||
| 
								 | 
							
								class TransformPromiseNode final: public TransformPromiseNodeBase {
							 | 
						||
| 
								 | 
							
								  // A PromiseNode that transforms the result of another PromiseNode through an application-provided
							 | 
						||
| 
								 | 
							
								  // function (implements `then()`).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  TransformPromiseNode(Own<PromiseNode>&& dependency, Func&& func, ErrorFunc&& errorHandler)
							 | 
						||
| 
								 | 
							
								      : TransformPromiseNodeBase(kj::mv(dependency),
							 | 
						||
| 
								 | 
							
								            GetFunctorStartAddress<DepT&&>::apply(func)),
							 | 
						||
| 
								 | 
							
								        func(kj::fwd<Func>(func)), errorHandler(kj::fwd<ErrorFunc>(errorHandler)) {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  ~TransformPromiseNode() noexcept(false) {
							 | 
						||
| 
								 | 
							
								    // We need to make sure the dependency is deleted before we delete the continuations because it
							 | 
						||
| 
								 | 
							
								    // is a common pattern for the continuations to hold ownership of objects that might be in-use
							 | 
						||
| 
								 | 
							
								    // by the dependency.
							 | 
						||
| 
								 | 
							
								    dropDependency();
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								  Func func;
							 | 
						||
| 
								 | 
							
								  ErrorFunc errorHandler;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  void getImpl(ExceptionOrValue& output) override {
							 | 
						||
| 
								 | 
							
								    ExceptionOr<DepT> depResult;
							 | 
						||
| 
								 | 
							
								    getDepResult(depResult);
							 | 
						||
| 
								 | 
							
								    KJ_IF_MAYBE(depException, depResult.exception) {
							 | 
						||
| 
								 | 
							
								      output.as<T>() = handle(
							 | 
						||
| 
								 | 
							
								          MaybeVoidCaller<Exception, FixVoid<ReturnType<ErrorFunc, Exception>>>::apply(
							 | 
						||
| 
								 | 
							
								              errorHandler, kj::mv(*depException)));
							 | 
						||
| 
								 | 
							
								    } else KJ_IF_MAYBE(depValue, depResult.value) {
							 | 
						||
| 
								 | 
							
								      output.as<T>() = handle(MaybeVoidCaller<DepT, T>::apply(func, kj::mv(*depValue)));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  ExceptionOr<T> handle(T&& value) {
							 | 
						||
| 
								 | 
							
								    return kj::mv(value);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  ExceptionOr<T> handle(PropagateException::Bottom&& value) {
							 | 
						||
| 
								 | 
							
								    return ExceptionOr<T>(false, value.asException());
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// -------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class ForkHubBase;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class ForkBranchBase: public PromiseNode {
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  ForkBranchBase(Own<ForkHubBase>&& hub);
							 | 
						||
| 
								 | 
							
								  ~ForkBranchBase() noexcept(false);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  void hubReady() noexcept;
							 | 
						||
| 
								 | 
							
								  // Called by the hub to indicate that it is ready.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // implements PromiseNode ------------------------------------------
							 | 
						||
| 
								 | 
							
								  void onReady(Event& event) noexcept override;
							 | 
						||
| 
								 | 
							
								  PromiseNode* getInnerForTrace() override;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								protected:
							 | 
						||
| 
								 | 
							
								  inline ExceptionOrValue& getHubResultRef();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  void releaseHub(ExceptionOrValue& output);
							 | 
						||
| 
								 | 
							
								  // Release the hub.  If an exception is thrown, add it to `output`.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								  OnReadyEvent onReadyEvent;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Own<ForkHubBase> hub;
							 | 
						||
| 
								 | 
							
								  ForkBranchBase* next = nullptr;
							 | 
						||
| 
								 | 
							
								  ForkBranchBase** prevPtr = nullptr;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  friend class ForkHubBase;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename T> T copyOrAddRef(T& t) { return t; }
							 | 
						||
| 
								 | 
							
								template <typename T> Own<T> copyOrAddRef(Own<T>& t) { return t->addRef(); }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename T>
							 | 
						||
| 
								 | 
							
								class ForkBranch final: public ForkBranchBase {
							 | 
						||
| 
								 | 
							
								  // A PromiseNode that implements one branch of a fork -- i.e. one of the branches that receives
							 | 
						||
| 
								 | 
							
								  // a const reference.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  ForkBranch(Own<ForkHubBase>&& hub): ForkBranchBase(kj::mv(hub)) {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  void get(ExceptionOrValue& output) noexcept override {
							 | 
						||
| 
								 | 
							
								    ExceptionOr<T>& hubResult = getHubResultRef().template as<T>();
							 | 
						||
| 
								 | 
							
								    KJ_IF_MAYBE(value, hubResult.value) {
							 | 
						||
| 
								 | 
							
								      output.as<T>().value = copyOrAddRef(*value);
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								      output.as<T>().value = nullptr;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    output.exception = hubResult.exception;
							 | 
						||
| 
								 | 
							
								    releaseHub(output);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename T, size_t index>
							 | 
						||
| 
								 | 
							
								class SplitBranch final: public ForkBranchBase {
							 | 
						||
| 
								 | 
							
								  // A PromiseNode that implements one branch of a fork -- i.e. one of the branches that receives
							 | 
						||
| 
								 | 
							
								  // a const reference.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  SplitBranch(Own<ForkHubBase>&& hub): ForkBranchBase(kj::mv(hub)) {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  typedef kj::Decay<decltype(kj::get<index>(kj::instance<T>()))> Element;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  void get(ExceptionOrValue& output) noexcept override {
							 | 
						||
| 
								 | 
							
								    ExceptionOr<T>& hubResult = getHubResultRef().template as<T>();
							 | 
						||
| 
								 | 
							
								    KJ_IF_MAYBE(value, hubResult.value) {
							 | 
						||
| 
								 | 
							
								      output.as<Element>().value = kj::mv(kj::get<index>(*value));
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								      output.as<Element>().value = nullptr;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    output.exception = hubResult.exception;
							 | 
						||
| 
								 | 
							
								    releaseHub(output);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// -------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class ForkHubBase: public Refcounted, protected Event {
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  ForkHubBase(Own<PromiseNode>&& inner, ExceptionOrValue& resultRef);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  inline ExceptionOrValue& getResultRef() { return resultRef; }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								  Own<PromiseNode> inner;
							 | 
						||
| 
								 | 
							
								  ExceptionOrValue& resultRef;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  ForkBranchBase* headBranch = nullptr;
							 | 
						||
| 
								 | 
							
								  ForkBranchBase** tailBranch = &headBranch;
							 | 
						||
| 
								 | 
							
								  // Tail becomes null once the inner promise is ready and all branches have been notified.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Maybe<Own<Event>> fire() override;
							 | 
						||
| 
								 | 
							
								  _::PromiseNode* getInnerForTrace() override;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  friend class ForkBranchBase;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename T>
							 | 
						||
| 
								 | 
							
								class ForkHub final: public ForkHubBase {
							 | 
						||
| 
								 | 
							
								  // A PromiseNode that implements the hub of a fork.  The first call to Promise::fork() replaces
							 | 
						||
| 
								 | 
							
								  // the promise's outer node with a ForkHub, and subsequent calls add branches to that hub (if
							 | 
						||
| 
								 | 
							
								  // possible).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  ForkHub(Own<PromiseNode>&& inner): ForkHubBase(kj::mv(inner), result) {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Promise<_::UnfixVoid<T>> addBranch() {
							 | 
						||
| 
								 | 
							
								    return Promise<_::UnfixVoid<T>>(false, kj::heap<ForkBranch<T>>(addRef(*this)));
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  _::SplitTuplePromise<T> split() {
							 | 
						||
| 
								 | 
							
								    return splitImpl(MakeIndexes<tupleSize<T>()>());
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								  ExceptionOr<T> result;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  template <size_t... indexes>
							 | 
						||
| 
								 | 
							
								  _::SplitTuplePromise<T> splitImpl(Indexes<indexes...>) {
							 | 
						||
| 
								 | 
							
								    return kj::tuple(addSplit<indexes>()...);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  template <size_t index>
							 | 
						||
| 
								 | 
							
								  Promise<JoinPromises<typename SplitBranch<T, index>::Element>> addSplit() {
							 | 
						||
| 
								 | 
							
								    return Promise<JoinPromises<typename SplitBranch<T, index>::Element>>(
							 | 
						||
| 
								 | 
							
								        false, maybeChain(kj::heap<SplitBranch<T, index>>(addRef(*this)),
							 | 
						||
| 
								 | 
							
								                          implicitCast<typename SplitBranch<T, index>::Element*>(nullptr)));
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								inline ExceptionOrValue& ForkBranchBase::getHubResultRef() {
							 | 
						||
| 
								 | 
							
								  return hub->getResultRef();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// -------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class ChainPromiseNode final: public PromiseNode, public Event {
							 | 
						||
| 
								 | 
							
								  // Promise node which reduces Promise<Promise<T>> to Promise<T>.
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // `Event` is only a public base class because otherwise we can't cast Own<ChainPromiseNode> to
							 | 
						||
| 
								 | 
							
								  // Own<Event>.  Ugh, templates and private...
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  explicit ChainPromiseNode(Own<PromiseNode> inner);
							 | 
						||
| 
								 | 
							
								  ~ChainPromiseNode() noexcept(false);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  void onReady(Event& event) noexcept override;
							 | 
						||
| 
								 | 
							
								  void setSelfPointer(Own<PromiseNode>* selfPtr) noexcept override;
							 | 
						||
| 
								 | 
							
								  void get(ExceptionOrValue& output) noexcept override;
							 | 
						||
| 
								 | 
							
								  PromiseNode* getInnerForTrace() override;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								  enum State {
							 | 
						||
| 
								 | 
							
								    STEP1,
							 | 
						||
| 
								 | 
							
								    STEP2
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  State state;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Own<PromiseNode> inner;
							 | 
						||
| 
								 | 
							
								  // In STEP1, a PromiseNode for a Promise<T>.
							 | 
						||
| 
								 | 
							
								  // In STEP2, a PromiseNode for a T.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Event* onReadyEvent = nullptr;
							 | 
						||
| 
								 | 
							
								  Own<PromiseNode>* selfPtr = nullptr;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Maybe<Own<Event>> fire() override;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename T>
							 | 
						||
| 
								 | 
							
								Own<PromiseNode> maybeChain(Own<PromiseNode>&& node, Promise<T>*) {
							 | 
						||
| 
								 | 
							
								  return heap<ChainPromiseNode>(kj::mv(node));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename T>
							 | 
						||
| 
								 | 
							
								Own<PromiseNode>&& maybeChain(Own<PromiseNode>&& node, T*) {
							 | 
						||
| 
								 | 
							
								  return kj::mv(node);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// -------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class ExclusiveJoinPromiseNode final: public PromiseNode {
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  ExclusiveJoinPromiseNode(Own<PromiseNode> left, Own<PromiseNode> right);
							 | 
						||
| 
								 | 
							
								  ~ExclusiveJoinPromiseNode() noexcept(false);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  void onReady(Event& event) noexcept override;
							 | 
						||
| 
								 | 
							
								  void get(ExceptionOrValue& output) noexcept override;
							 | 
						||
| 
								 | 
							
								  PromiseNode* getInnerForTrace() override;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								  class Branch: public Event {
							 | 
						||
| 
								 | 
							
								  public:
							 | 
						||
| 
								 | 
							
								    Branch(ExclusiveJoinPromiseNode& joinNode, Own<PromiseNode> dependency);
							 | 
						||
| 
								 | 
							
								    ~Branch() noexcept(false);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    bool get(ExceptionOrValue& output);
							 | 
						||
| 
								 | 
							
								    // Returns true if this is the side that finished.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Maybe<Own<Event>> fire() override;
							 | 
						||
| 
								 | 
							
								    _::PromiseNode* getInnerForTrace() override;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  private:
							 | 
						||
| 
								 | 
							
								    ExclusiveJoinPromiseNode& joinNode;
							 | 
						||
| 
								 | 
							
								    Own<PromiseNode> dependency;
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Branch left;
							 | 
						||
| 
								 | 
							
								  Branch right;
							 | 
						||
| 
								 | 
							
								  OnReadyEvent onReadyEvent;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// -------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class ArrayJoinPromiseNodeBase: public PromiseNode {
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  ArrayJoinPromiseNodeBase(Array<Own<PromiseNode>> promises,
							 | 
						||
| 
								 | 
							
								                           ExceptionOrValue* resultParts, size_t partSize);
							 | 
						||
| 
								 | 
							
								  ~ArrayJoinPromiseNodeBase() noexcept(false);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  void onReady(Event& event) noexcept override final;
							 | 
						||
| 
								 | 
							
								  void get(ExceptionOrValue& output) noexcept override final;
							 | 
						||
| 
								 | 
							
								  PromiseNode* getInnerForTrace() override final;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								protected:
							 | 
						||
| 
								 | 
							
								  virtual void getNoError(ExceptionOrValue& output) noexcept = 0;
							 | 
						||
| 
								 | 
							
								  // Called to compile the result only in the case where there were no errors.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								  uint countLeft;
							 | 
						||
| 
								 | 
							
								  OnReadyEvent onReadyEvent;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  class Branch final: public Event {
							 | 
						||
| 
								 | 
							
								  public:
							 | 
						||
| 
								 | 
							
								    Branch(ArrayJoinPromiseNodeBase& joinNode, Own<PromiseNode> dependency,
							 | 
						||
| 
								 | 
							
								           ExceptionOrValue& output);
							 | 
						||
| 
								 | 
							
								    ~Branch() noexcept(false);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Maybe<Own<Event>> fire() override;
							 | 
						||
| 
								 | 
							
								    _::PromiseNode* getInnerForTrace() override;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Maybe<Exception> getPart();
							 | 
						||
| 
								 | 
							
								    // Calls dependency->get(output).  If there was an exception, return it.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  private:
							 | 
						||
| 
								 | 
							
								    ArrayJoinPromiseNodeBase& joinNode;
							 | 
						||
| 
								 | 
							
								    Own<PromiseNode> dependency;
							 | 
						||
| 
								 | 
							
								    ExceptionOrValue& output;
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Array<Branch> branches;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename T>
							 | 
						||
| 
								 | 
							
								class ArrayJoinPromiseNode final: public ArrayJoinPromiseNodeBase {
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  ArrayJoinPromiseNode(Array<Own<PromiseNode>> promises,
							 | 
						||
| 
								 | 
							
								                       Array<ExceptionOr<T>> resultParts)
							 | 
						||
| 
								 | 
							
								      : ArrayJoinPromiseNodeBase(kj::mv(promises), resultParts.begin(), sizeof(ExceptionOr<T>)),
							 | 
						||
| 
								 | 
							
								        resultParts(kj::mv(resultParts)) {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								protected:
							 | 
						||
| 
								 | 
							
								  void getNoError(ExceptionOrValue& output) noexcept override {
							 | 
						||
| 
								 | 
							
								    auto builder = heapArrayBuilder<T>(resultParts.size());
							 | 
						||
| 
								 | 
							
								    for (auto& part: resultParts) {
							 | 
						||
| 
								 | 
							
								      KJ_IASSERT(part.value != nullptr,
							 | 
						||
| 
								 | 
							
								                 "Bug in KJ promise framework:  Promise result had neither value no exception.");
							 | 
						||
| 
								 | 
							
								      builder.add(kj::mv(*_::readMaybe(part.value)));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    output.as<Array<T>>() = builder.finish();
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								  Array<ExceptionOr<T>> resultParts;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <>
							 | 
						||
| 
								 | 
							
								class ArrayJoinPromiseNode<void> final: public ArrayJoinPromiseNodeBase {
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  ArrayJoinPromiseNode(Array<Own<PromiseNode>> promises,
							 | 
						||
| 
								 | 
							
								                       Array<ExceptionOr<_::Void>> resultParts);
							 | 
						||
| 
								 | 
							
								  ~ArrayJoinPromiseNode();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								protected:
							 | 
						||
| 
								 | 
							
								  void getNoError(ExceptionOrValue& output) noexcept override;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								  Array<ExceptionOr<_::Void>> resultParts;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// -------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class EagerPromiseNodeBase: public PromiseNode, protected Event {
							 | 
						||
| 
								 | 
							
								  // A PromiseNode that eagerly evaluates its dependency even if its dependent does not eagerly
							 | 
						||
| 
								 | 
							
								  // evaluate it.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  EagerPromiseNodeBase(Own<PromiseNode>&& dependency, ExceptionOrValue& resultRef);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  void onReady(Event& event) noexcept override;
							 | 
						||
| 
								 | 
							
								  PromiseNode* getInnerForTrace() override;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								  Own<PromiseNode> dependency;
							 | 
						||
| 
								 | 
							
								  OnReadyEvent onReadyEvent;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  ExceptionOrValue& resultRef;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Maybe<Own<Event>> fire() override;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename T>
							 | 
						||
| 
								 | 
							
								class EagerPromiseNode final: public EagerPromiseNodeBase {
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  EagerPromiseNode(Own<PromiseNode>&& dependency)
							 | 
						||
| 
								 | 
							
								      : EagerPromiseNodeBase(kj::mv(dependency), result) {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  void get(ExceptionOrValue& output) noexcept override {
							 | 
						||
| 
								 | 
							
								    output.as<T>() = kj::mv(result);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								  ExceptionOr<T> result;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename T>
							 | 
						||
| 
								 | 
							
								Own<PromiseNode> spark(Own<PromiseNode>&& node) {
							 | 
						||
| 
								 | 
							
								  // Forces evaluation of the given node to begin as soon as possible, even if no one is waiting
							 | 
						||
| 
								 | 
							
								  // on it.
							 | 
						||
| 
								 | 
							
								  return heap<EagerPromiseNode<T>>(kj::mv(node));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// -------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class AdapterPromiseNodeBase: public PromiseNode {
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  void onReady(Event& event) noexcept override;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								protected:
							 | 
						||
| 
								 | 
							
								  inline void setReady() {
							 | 
						||
| 
								 | 
							
								    onReadyEvent.arm();
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								  OnReadyEvent onReadyEvent;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename T, typename Adapter>
							 | 
						||
| 
								 | 
							
								class AdapterPromiseNode final: public AdapterPromiseNodeBase,
							 | 
						||
| 
								 | 
							
								                                private PromiseFulfiller<UnfixVoid<T>> {
							 | 
						||
| 
								 | 
							
								  // A PromiseNode that wraps a PromiseAdapter.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  template <typename... Params>
							 | 
						||
| 
								 | 
							
								  AdapterPromiseNode(Params&&... params)
							 | 
						||
| 
								 | 
							
								      : adapter(static_cast<PromiseFulfiller<UnfixVoid<T>>&>(*this), kj::fwd<Params>(params)...) {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  void get(ExceptionOrValue& output) noexcept override {
							 | 
						||
| 
								 | 
							
								    KJ_IREQUIRE(!isWaiting());
							 | 
						||
| 
								 | 
							
								    output.as<T>() = kj::mv(result);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								  ExceptionOr<T> result;
							 | 
						||
| 
								 | 
							
								  bool waiting = true;
							 | 
						||
| 
								 | 
							
								  Adapter adapter;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  void fulfill(T&& value) override {
							 | 
						||
| 
								 | 
							
								    if (waiting) {
							 | 
						||
| 
								 | 
							
								      waiting = false;
							 | 
						||
| 
								 | 
							
								      result = ExceptionOr<T>(kj::mv(value));
							 | 
						||
| 
								 | 
							
								      setReady();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  void reject(Exception&& exception) override {
							 | 
						||
| 
								 | 
							
								    if (waiting) {
							 | 
						||
| 
								 | 
							
								      waiting = false;
							 | 
						||
| 
								 | 
							
								      result = ExceptionOr<T>(false, kj::mv(exception));
							 | 
						||
| 
								 | 
							
								      setReady();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  bool isWaiting() override {
							 | 
						||
| 
								 | 
							
								    return waiting;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}  // namespace _ (private)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// =======================================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename T>
							 | 
						||
| 
								 | 
							
								Promise<T>::Promise(_::FixVoid<T> value)
							 | 
						||
| 
								 | 
							
								    : PromiseBase(heap<_::ImmediatePromiseNode<_::FixVoid<T>>>(kj::mv(value))) {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename T>
							 | 
						||
| 
								 | 
							
								Promise<T>::Promise(kj::Exception&& exception)
							 | 
						||
| 
								 | 
							
								    : PromiseBase(heap<_::ImmediateBrokenPromiseNode>(kj::mv(exception))) {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename T>
							 | 
						||
| 
								 | 
							
								template <typename Func, typename ErrorFunc>
							 | 
						||
| 
								 | 
							
								PromiseForResult<Func, T> Promise<T>::then(Func&& func, ErrorFunc&& errorHandler) {
							 | 
						||
| 
								 | 
							
								  typedef _::FixVoid<_::ReturnType<Func, T>> ResultT;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Own<_::PromiseNode> intermediate =
							 | 
						||
| 
								 | 
							
								      heap<_::TransformPromiseNode<ResultT, _::FixVoid<T>, Func, ErrorFunc>>(
							 | 
						||
| 
								 | 
							
								          kj::mv(node), kj::fwd<Func>(func), kj::fwd<ErrorFunc>(errorHandler));
							 | 
						||
| 
								 | 
							
								  return PromiseForResult<Func, T>(false,
							 | 
						||
| 
								 | 
							
								      _::maybeChain(kj::mv(intermediate), implicitCast<ResultT*>(nullptr)));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace _ {  // private
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename T>
							 | 
						||
| 
								 | 
							
								struct IdentityFunc {
							 | 
						||
| 
								 | 
							
								  inline T operator()(T&& value) const {
							 | 
						||
| 
								 | 
							
								    return kj::mv(value);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								template <typename T>
							 | 
						||
| 
								 | 
							
								struct IdentityFunc<Promise<T>> {
							 | 
						||
| 
								 | 
							
								  inline Promise<T> operator()(T&& value) const {
							 | 
						||
| 
								 | 
							
								    return kj::mv(value);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								template <>
							 | 
						||
| 
								 | 
							
								struct IdentityFunc<void> {
							 | 
						||
| 
								 | 
							
								  inline void operator()() const {}
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								template <>
							 | 
						||
| 
								 | 
							
								struct IdentityFunc<Promise<void>> {
							 | 
						||
| 
								 | 
							
								  Promise<void> operator()() const;
							 | 
						||
| 
								 | 
							
								  // This can't be inline because it will make the translation unit depend on kj-async. Awkwardly,
							 | 
						||
| 
								 | 
							
								  // Cap'n Proto relies on being able to include this header without creating such a link-time
							 | 
						||
| 
								 | 
							
								  // dependency.
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}  // namespace _ (private)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename T>
							 | 
						||
| 
								 | 
							
								template <typename ErrorFunc>
							 | 
						||
| 
								 | 
							
								Promise<T> Promise<T>::catch_(ErrorFunc&& errorHandler) {
							 | 
						||
| 
								 | 
							
								  // then()'s ErrorFunc can only return a Promise if Func also returns a Promise. In this case,
							 | 
						||
| 
								 | 
							
								  // Func is being filled in automatically. We want to make sure ErrorFunc can return a Promise,
							 | 
						||
| 
								 | 
							
								  // but we don't want the extra overhead of promise chaining if ErrorFunc doesn't actually
							 | 
						||
| 
								 | 
							
								  // return a promise. So we make our Func return match ErrorFunc.
							 | 
						||
| 
								 | 
							
								  return then(_::IdentityFunc<decltype(errorHandler(instance<Exception&&>()))>(),
							 | 
						||
| 
								 | 
							
								              kj::fwd<ErrorFunc>(errorHandler));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename T>
							 | 
						||
| 
								 | 
							
								T Promise<T>::wait(WaitScope& waitScope) {
							 | 
						||
| 
								 | 
							
								  _::ExceptionOr<_::FixVoid<T>> result;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  waitImpl(kj::mv(node), result, waitScope);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  KJ_IF_MAYBE(value, result.value) {
							 | 
						||
| 
								 | 
							
								    KJ_IF_MAYBE(exception, result.exception) {
							 | 
						||
| 
								 | 
							
								      throwRecoverableException(kj::mv(*exception));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return _::returnMaybeVoid(kj::mv(*value));
							 | 
						||
| 
								 | 
							
								  } else KJ_IF_MAYBE(exception, result.exception) {
							 | 
						||
| 
								 | 
							
								    throwFatalException(kj::mv(*exception));
							 | 
						||
| 
								 | 
							
								  } else {
							 | 
						||
| 
								 | 
							
								    // Result contained neither a value nor an exception?
							 | 
						||
| 
								 | 
							
								    KJ_UNREACHABLE;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <>
							 | 
						||
| 
								 | 
							
								inline void Promise<void>::wait(WaitScope& waitScope) {
							 | 
						||
| 
								 | 
							
								  // Override <void> case to use throwRecoverableException().
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  _::ExceptionOr<_::Void> result;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  waitImpl(kj::mv(node), result, waitScope);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (result.value != nullptr) {
							 | 
						||
| 
								 | 
							
								    KJ_IF_MAYBE(exception, result.exception) {
							 | 
						||
| 
								 | 
							
								      throwRecoverableException(kj::mv(*exception));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  } else KJ_IF_MAYBE(exception, result.exception) {
							 | 
						||
| 
								 | 
							
								    throwRecoverableException(kj::mv(*exception));
							 | 
						||
| 
								 | 
							
								  } else {
							 | 
						||
| 
								 | 
							
								    // Result contained neither a value nor an exception?
							 | 
						||
| 
								 | 
							
								    KJ_UNREACHABLE;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename T>
							 | 
						||
| 
								 | 
							
								ForkedPromise<T> Promise<T>::fork() {
							 | 
						||
| 
								 | 
							
								  return ForkedPromise<T>(false, refcounted<_::ForkHub<_::FixVoid<T>>>(kj::mv(node)));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename T>
							 | 
						||
| 
								 | 
							
								Promise<T> ForkedPromise<T>::addBranch() {
							 | 
						||
| 
								 | 
							
								  return hub->addBranch();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename T>
							 | 
						||
| 
								 | 
							
								_::SplitTuplePromise<T> Promise<T>::split() {
							 | 
						||
| 
								 | 
							
								  return refcounted<_::ForkHub<_::FixVoid<T>>>(kj::mv(node))->split();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename T>
							 | 
						||
| 
								 | 
							
								Promise<T> Promise<T>::exclusiveJoin(Promise<T>&& other) {
							 | 
						||
| 
								 | 
							
								  return Promise(false, heap<_::ExclusiveJoinPromiseNode>(kj::mv(node), kj::mv(other.node)));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename T>
							 | 
						||
| 
								 | 
							
								template <typename... Attachments>
							 | 
						||
| 
								 | 
							
								Promise<T> Promise<T>::attach(Attachments&&... attachments) {
							 | 
						||
| 
								 | 
							
								  return Promise(false, kj::heap<_::AttachmentPromiseNode<Tuple<Attachments...>>>(
							 | 
						||
| 
								 | 
							
								      kj::mv(node), kj::tuple(kj::fwd<Attachments>(attachments)...)));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename T>
							 | 
						||
| 
								 | 
							
								template <typename ErrorFunc>
							 | 
						||
| 
								 | 
							
								Promise<T> Promise<T>::eagerlyEvaluate(ErrorFunc&& errorHandler) {
							 | 
						||
| 
								 | 
							
								  // See catch_() for commentary.
							 | 
						||
| 
								 | 
							
								  return Promise(false, _::spark<_::FixVoid<T>>(then(
							 | 
						||
| 
								 | 
							
								      _::IdentityFunc<decltype(errorHandler(instance<Exception&&>()))>(),
							 | 
						||
| 
								 | 
							
								      kj::fwd<ErrorFunc>(errorHandler)).node));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename T>
							 | 
						||
| 
								 | 
							
								Promise<T> Promise<T>::eagerlyEvaluate(decltype(nullptr)) {
							 | 
						||
| 
								 | 
							
								  return Promise(false, _::spark<_::FixVoid<T>>(kj::mv(node)));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename T>
							 | 
						||
| 
								 | 
							
								kj::String Promise<T>::trace() {
							 | 
						||
| 
								 | 
							
								  return PromiseBase::trace();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename Func>
							 | 
						||
| 
								 | 
							
								inline PromiseForResult<Func, void> evalLater(Func&& func) {
							 | 
						||
| 
								 | 
							
								  return _::yield().then(kj::fwd<Func>(func), _::PropagateException());
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename Func>
							 | 
						||
| 
								 | 
							
								inline PromiseForResult<Func, void> evalNow(Func&& func) {
							 | 
						||
| 
								 | 
							
								  PromiseForResult<Func, void> result = nullptr;
							 | 
						||
| 
								 | 
							
								  KJ_IF_MAYBE(e, kj::runCatchingExceptions([&]() {
							 | 
						||
| 
								 | 
							
								    result = func();
							 | 
						||
| 
								 | 
							
								  })) {
							 | 
						||
| 
								 | 
							
								    result = kj::mv(*e);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return result;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename T>
							 | 
						||
| 
								 | 
							
								template <typename ErrorFunc>
							 | 
						||
| 
								 | 
							
								void Promise<T>::detach(ErrorFunc&& errorHandler) {
							 | 
						||
| 
								 | 
							
								  return _::detach(then([](T&&) {}, kj::fwd<ErrorFunc>(errorHandler)));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <>
							 | 
						||
| 
								 | 
							
								template <typename ErrorFunc>
							 | 
						||
| 
								 | 
							
								void Promise<void>::detach(ErrorFunc&& errorHandler) {
							 | 
						||
| 
								 | 
							
								  return _::detach(then([]() {}, kj::fwd<ErrorFunc>(errorHandler)));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename T>
							 | 
						||
| 
								 | 
							
								Promise<Array<T>> joinPromises(Array<Promise<T>>&& promises) {
							 | 
						||
| 
								 | 
							
								  return Promise<Array<T>>(false, kj::heap<_::ArrayJoinPromiseNode<T>>(
							 | 
						||
| 
								 | 
							
								      KJ_MAP(p, promises) { return kj::mv(p.node); },
							 | 
						||
| 
								 | 
							
								      heapArray<_::ExceptionOr<T>>(promises.size())));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// =======================================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace _ {  // private
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename T>
							 | 
						||
| 
								 | 
							
								class WeakFulfiller final: public PromiseFulfiller<T>, private kj::Disposer {
							 | 
						||
| 
								 | 
							
								  // A wrapper around PromiseFulfiller which can be detached.
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // There are a couple non-trivialities here:
							 | 
						||
| 
								 | 
							
								  // - If the WeakFulfiller is discarded, we want the promise it fulfills to be implicitly
							 | 
						||
| 
								 | 
							
								  //   rejected.
							 | 
						||
| 
								 | 
							
								  // - We cannot destroy the WeakFulfiller until the application has discarded it *and* it has been
							 | 
						||
| 
								 | 
							
								  //   detached from the underlying fulfiller, because otherwise the later detach() call will go
							 | 
						||
| 
								 | 
							
								  //   to a dangling pointer.  Essentially, WeakFulfiller is reference counted, although the
							 | 
						||
| 
								 | 
							
								  //   refcount never goes over 2 and we manually implement the refcounting because we need to do
							 | 
						||
| 
								 | 
							
								  //   other special things when each side detaches anyway.  To this end, WeakFulfiller is its own
							 | 
						||
| 
								 | 
							
								  //   Disposer -- dispose() is called when the application discards its owned pointer to the
							 | 
						||
| 
								 | 
							
								  //   fulfiller and detach() is called when the promise is destroyed.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  KJ_DISALLOW_COPY(WeakFulfiller);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  static kj::Own<WeakFulfiller> make() {
							 | 
						||
| 
								 | 
							
								    WeakFulfiller* ptr = new WeakFulfiller;
							 | 
						||
| 
								 | 
							
								    return Own<WeakFulfiller>(ptr, *ptr);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  void fulfill(FixVoid<T>&& value) override {
							 | 
						||
| 
								 | 
							
								    if (inner != nullptr) {
							 | 
						||
| 
								 | 
							
								      inner->fulfill(kj::mv(value));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  void reject(Exception&& exception) override {
							 | 
						||
| 
								 | 
							
								    if (inner != nullptr) {
							 | 
						||
| 
								 | 
							
								      inner->reject(kj::mv(exception));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  bool isWaiting() override {
							 | 
						||
| 
								 | 
							
								    return inner != nullptr && inner->isWaiting();
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  void attach(PromiseFulfiller<T>& newInner) {
							 | 
						||
| 
								 | 
							
								    inner = &newInner;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  void detach(PromiseFulfiller<T>& from) {
							 | 
						||
| 
								 | 
							
								    if (inner == nullptr) {
							 | 
						||
| 
								 | 
							
								      // Already disposed.
							 | 
						||
| 
								 | 
							
								      delete this;
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								      KJ_IREQUIRE(inner == &from);
							 | 
						||
| 
								 | 
							
								      inner = nullptr;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								  mutable PromiseFulfiller<T>* inner;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  WeakFulfiller(): inner(nullptr) {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  void disposeImpl(void* pointer) const override {
							 | 
						||
| 
								 | 
							
								    // TODO(perf): Factor some of this out so it isn't regenerated for every fulfiller type?
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (inner == nullptr) {
							 | 
						||
| 
								 | 
							
								      // Already detached.
							 | 
						||
| 
								 | 
							
								      delete this;
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								      if (inner->isWaiting()) {
							 | 
						||
| 
								 | 
							
								        inner->reject(kj::Exception(kj::Exception::Type::FAILED, __FILE__, __LINE__,
							 | 
						||
| 
								 | 
							
								            kj::heapString("PromiseFulfiller was destroyed without fulfilling the promise.")));
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      inner = nullptr;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename T>
							 | 
						||
| 
								 | 
							
								class PromiseAndFulfillerAdapter {
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  PromiseAndFulfillerAdapter(PromiseFulfiller<T>& fulfiller,
							 | 
						||
| 
								 | 
							
								                             WeakFulfiller<T>& wrapper)
							 | 
						||
| 
								 | 
							
								      : fulfiller(fulfiller), wrapper(wrapper) {
							 | 
						||
| 
								 | 
							
								    wrapper.attach(fulfiller);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  ~PromiseAndFulfillerAdapter() noexcept(false) {
							 | 
						||
| 
								 | 
							
								    wrapper.detach(fulfiller);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								  PromiseFulfiller<T>& fulfiller;
							 | 
						||
| 
								 | 
							
								  WeakFulfiller<T>& wrapper;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}  // namespace _ (private)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename T>
							 | 
						||
| 
								 | 
							
								template <typename Func>
							 | 
						||
| 
								 | 
							
								bool PromiseFulfiller<T>::rejectIfThrows(Func&& func) {
							 | 
						||
| 
								 | 
							
								  KJ_IF_MAYBE(exception, kj::runCatchingExceptions(kj::mv(func))) {
							 | 
						||
| 
								 | 
							
								    reject(kj::mv(*exception));
							 | 
						||
| 
								 | 
							
								    return false;
							 | 
						||
| 
								 | 
							
								  } else {
							 | 
						||
| 
								 | 
							
								    return true;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename Func>
							 | 
						||
| 
								 | 
							
								bool PromiseFulfiller<void>::rejectIfThrows(Func&& func) {
							 | 
						||
| 
								 | 
							
								  KJ_IF_MAYBE(exception, kj::runCatchingExceptions(kj::mv(func))) {
							 | 
						||
| 
								 | 
							
								    reject(kj::mv(*exception));
							 | 
						||
| 
								 | 
							
								    return false;
							 | 
						||
| 
								 | 
							
								  } else {
							 | 
						||
| 
								 | 
							
								    return true;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename T, typename Adapter, typename... Params>
							 | 
						||
| 
								 | 
							
								Promise<T> newAdaptedPromise(Params&&... adapterConstructorParams) {
							 | 
						||
| 
								 | 
							
								  return Promise<T>(false, heap<_::AdapterPromiseNode<_::FixVoid<T>, Adapter>>(
							 | 
						||
| 
								 | 
							
								      kj::fwd<Params>(adapterConstructorParams)...));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename T>
							 | 
						||
| 
								 | 
							
								PromiseFulfillerPair<T> newPromiseAndFulfiller() {
							 | 
						||
| 
								 | 
							
								  auto wrapper = _::WeakFulfiller<T>::make();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Own<_::PromiseNode> intermediate(
							 | 
						||
| 
								 | 
							
								      heap<_::AdapterPromiseNode<_::FixVoid<T>, _::PromiseAndFulfillerAdapter<T>>>(*wrapper));
							 | 
						||
| 
								 | 
							
								  Promise<_::JoinPromises<T>> promise(false,
							 | 
						||
| 
								 | 
							
								      _::maybeChain(kj::mv(intermediate), implicitCast<T*>(nullptr)));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return PromiseFulfillerPair<T> { kj::mv(promise), kj::mv(wrapper) };
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}  // namespace kj
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif  // KJ_ASYNC_INL_H_
							 |