LCOV - code coverage report
Current view: top level - include/llvm/ExecutionEngine/Orc - RPCUtils.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 1151 2191 52.5 %
Date: 2018-10-20 13:21:21 Functions: 222 624 35.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===------- RPCUTils.h - Utilities for building RPC APIs -------*- C++ -*-===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : //
      10             : // Utilities to support construction of simple RPC APIs.
      11             : //
      12             : // The RPC utilities aim for ease of use (minimal conceptual overhead) for C++
      13             : // programmers, high performance, low memory overhead, and efficient use of the
      14             : // communications channel.
      15             : //
      16             : //===----------------------------------------------------------------------===//
      17             : 
      18             : #ifndef LLVM_EXECUTIONENGINE_ORC_RPCUTILS_H
      19             : #define LLVM_EXECUTIONENGINE_ORC_RPCUTILS_H
      20             : 
      21             : #include <map>
      22             : #include <thread>
      23             : #include <vector>
      24             : 
      25             : #include "llvm/ADT/STLExtras.h"
      26             : #include "llvm/ExecutionEngine/Orc/OrcError.h"
      27             : #include "llvm/ExecutionEngine/Orc/RPCSerialization.h"
      28             : #include "llvm/Support/MSVCErrorWorkarounds.h"
      29             : 
      30             : #include <future>
      31             : 
      32             : namespace llvm {
      33             : namespace orc {
      34             : namespace rpc {
      35             : 
      36             : /// Base class of all fatal RPC errors (those that necessarily result in the
      37             : /// termination of the RPC session).
      38             : class RPCFatalError : public ErrorInfo<RPCFatalError> {
      39             : public:
      40             :   static char ID;
      41             : };
      42             : 
      43             : /// RPCConnectionClosed is returned from RPC operations if the RPC connection
      44             : /// has already been closed due to either an error or graceful disconnection.
      45             : class ConnectionClosed : public ErrorInfo<ConnectionClosed> {
      46             : public:
      47             :   static char ID;
      48             :   std::error_code convertToErrorCode() const override;
      49             :   void log(raw_ostream &OS) const override;
      50             : };
      51             : 
      52             : /// BadFunctionCall is returned from handleOne when the remote makes a call with
      53             : /// an unrecognized function id.
      54             : ///
      55             : /// This error is fatal because Orc RPC needs to know how to parse a function
      56             : /// call to know where the next call starts, and if it doesn't recognize the
      57             : /// function id it cannot parse the call.
      58             : template <typename FnIdT, typename SeqNoT>
      59             : class BadFunctionCall
      60             :   : public ErrorInfo<BadFunctionCall<FnIdT, SeqNoT>, RPCFatalError> {
      61             : public:
      62             :   static char ID;
      63             : 
      64           0 :   BadFunctionCall(FnIdT FnId, SeqNoT SeqNo)
      65           0 :       : FnId(std::move(FnId)), SeqNo(std::move(SeqNo)) {}
      66             : 
      67           0 :   std::error_code convertToErrorCode() const override {
      68           0 :     return orcError(OrcErrorCode::UnexpectedRPCCall);
      69             :   }
      70             : 
      71           0 :   void log(raw_ostream &OS) const override {
      72           0 :     OS << "Call to invalid RPC function id '" << FnId << "' with "
      73           0 :           "sequence number " << SeqNo;
      74           0 :   }
      75             : 
      76             : private:
      77             :   FnIdT FnId;
      78             :   SeqNoT SeqNo;
      79             : };
      80             : 
      81             : template <typename FnIdT, typename SeqNoT>
      82             : char BadFunctionCall<FnIdT, SeqNoT>::ID = 0;
      83             : 
      84             : /// InvalidSequenceNumberForResponse is returned from handleOne when a response
      85             : /// call arrives with a sequence number that doesn't correspond to any in-flight
      86             : /// function call.
      87             : ///
      88             : /// This error is fatal because Orc RPC needs to know how to parse the rest of
      89             : /// the response call to know where the next call starts, and if it doesn't have
      90             : /// a result parser for this sequence number it can't do that.
      91             : template <typename SeqNoT>
      92             : class InvalidSequenceNumberForResponse
      93             :     : public ErrorInfo<InvalidSequenceNumberForResponse<SeqNoT>, RPCFatalError> {
      94             : public:
      95             :   static char ID;
      96             : 
      97           0 :   InvalidSequenceNumberForResponse(SeqNoT SeqNo)
      98           0 :       : SeqNo(std::move(SeqNo)) {}
      99             : 
     100           0 :   std::error_code convertToErrorCode() const override {
     101           0 :     return orcError(OrcErrorCode::UnexpectedRPCCall);
     102             :   };
     103             : 
     104           0 :   void log(raw_ostream &OS) const override {
     105           0 :     OS << "Response has unknown sequence number " << SeqNo;
     106           0 :   }
     107             : private:
     108             :   SeqNoT SeqNo;
     109             : };
     110             : 
     111             : template <typename SeqNoT>
     112             : char InvalidSequenceNumberForResponse<SeqNoT>::ID = 0;
     113             : 
     114             : /// This non-fatal error will be passed to asynchronous result handlers in place
     115             : /// of a result if the connection goes down before a result returns, or if the
     116             : /// function to be called cannot be negotiated with the remote.
     117           0 : class ResponseAbandoned : public ErrorInfo<ResponseAbandoned> {
     118             : public:
     119             :   static char ID;
     120             : 
     121             :   std::error_code convertToErrorCode() const override;
     122             :   void log(raw_ostream &OS) const override;
     123             : };
     124             : 
     125             : /// This error is returned if the remote does not have a handler installed for
     126             : /// the given RPC function.
     127             : class CouldNotNegotiate : public ErrorInfo<CouldNotNegotiate> {
     128             : public:
     129             :   static char ID;
     130             : 
     131             :   CouldNotNegotiate(std::string Signature);
     132             :   std::error_code convertToErrorCode() const override;
     133             :   void log(raw_ostream &OS) const override;
     134             :   const std::string &getSignature() const { return Signature; }
     135             : private:
     136             :   std::string Signature;
     137             : };
     138             : 
     139             : template <typename DerivedFunc, typename FnT> class Function;
     140             : 
     141             : // RPC Function class.
     142             : // DerivedFunc should be a user defined class with a static 'getName()' method
     143             : // returning a const char* representing the function's name.
     144             : template <typename DerivedFunc, typename RetT, typename... ArgTs>
     145             : class Function<DerivedFunc, RetT(ArgTs...)> {
     146             : public:
     147             :   /// User defined function type.
     148             :   using Type = RetT(ArgTs...);
     149             : 
     150             :   /// Return type.
     151             :   using ReturnType = RetT;
     152             : 
     153             :   /// Returns the full function prototype as a string.
     154        1923 :   static const char *getPrototype() {
     155             :     std::lock_guard<std::mutex> Lock(NameMutex);
     156        1923 :     if (Name.empty())
     157             :       raw_string_ostream(Name)
     158        1908 :           << RPCTypeName<RetT>::getName() << " " << DerivedFunc::getName()
     159        1400 :           << "(" << llvm::orc::rpc::RPCTypeNameSequence<ArgTs...>() << ")";
     160        1923 :     return Name.data();
     161             :   }
     162          67 : 
     163             : private:
     164          67 :   static std::mutex NameMutex;
     165             :   static std::string Name;
     166          76 : };
     167          46 : 
     168          67 : template <typename DerivedFunc, typename RetT, typename... ArgTs>
     169             : std::mutex Function<DerivedFunc, RetT(ArgTs...)>::NameMutex;
     170          72 : 
     171             : template <typename DerivedFunc, typename RetT, typename... ArgTs>
     172          72 : std::string Function<DerivedFunc, RetT(ArgTs...)>::Name;
     173             : 
     174         116 : /// Allocates RPC function ids during autonegotiation.
     175          66 : /// Specializations of this class must provide four members:
     176          72 : ///
     177             : /// static T getInvalidId():
     178         275 : ///   Should return a reserved id that will be used to represent missing
     179             : /// functions during autonegotiation.
     180         275 : ///
     181             : /// static T getResponseId():
     182         118 : ///   Should return a reserved id that will be used to send function responses
     183         118 : /// (return values).
     184         275 : ///
     185             : /// static T getNegotiateId():
     186          68 : ///   Should return a reserved id for the negotiate function, which will be used
     187             : /// to negotiate ids for user defined functions.
     188          68 : ///
     189             : /// template <typename Func> T allocate():
     190         116 : ///   Allocate a unique id for function Func.
     191         106 : template <typename T, typename = void> class RPCFunctionIdAllocator;
     192          68 : 
     193             : /// This specialization of RPCFunctionIdAllocator provides a default
     194         115 : /// implementation for integral types.
     195             : template <typename T>
     196         115 : class RPCFunctionIdAllocator<
     197             :     T, typename std::enable_if<std::is_integral<T>::value>::type> {
     198         114 : public:
     199          82 :   static T getInvalidId() { return T(0); }
     200         115 :   static T getResponseId() { return T(1); }
     201             :   static T getNegotiateId() { return T(2); }
     202         134 : 
     203             :   template <typename Func> T allocate() { return NextId++; }
     204         134 : 
     205             : private:
     206         122 :   T NextId = 3;
     207         122 : };
     208         134 : 
     209             : namespace detail {
     210         137 : 
     211             : /// Provides a typedef for a tuple containing the decayed argument types.
     212         137 : template <typename T> class FunctionArgsTuple;
     213             : 
     214         110 : template <typename RetT, typename... ArgTs>
     215         110 : class FunctionArgsTuple<RetT(ArgTs...)> {
     216         137 : public:
     217             :   using Type = std::tuple<typename std::decay<
     218         137 :       typename std::remove_reference<ArgTs>::type>::type...>;
     219             : };
     220         137 : 
     221             : // ResultTraits provides typedefs and utilities specific to the return type
     222         148 : // of functions.
     223          98 : template <typename RetT> class ResultTraits {
     224         137 : public:
     225             :   // The return type wrapped in llvm::Expected.
     226         122 :   using ErrorReturnType = Expected<RetT>;
     227             : 
     228         122 : #ifdef _MSC_VER
     229             :   // The ErrorReturnType wrapped in a std::promise.
     230         124 :   using ReturnPromiseType = std::promise<MSVCPExpected<RetT>>;
     231          68 : 
     232         122 :   // The ErrorReturnType wrapped in a std::future.
     233             :   using ReturnFutureType = std::future<MSVCPExpected<RetT>>;
     234          56 : #else
     235             :   // The ErrorReturnType wrapped in a std::promise.
     236          56 :   using ReturnPromiseType = std::promise<ErrorReturnType>;
     237             : 
     238          64 :   // The ErrorReturnType wrapped in a std::future.
     239          32 :   using ReturnFutureType = std::future<ErrorReturnType>;
     240          56 : #endif
     241             : 
     242         136 :   // Create a 'blank' value of the ErrorReturnType, ready and safe to
     243             :   // overwrite.
     244         136 :   static ErrorReturnType createBlankErrorReturnValue() {
     245             :     return ErrorReturnType(RetT());
     246         112 :   }
     247          88 : 
     248         136 :   // Consume an abandoned ErrorReturnType.
     249             :   static void consumeAbandoned(ErrorReturnType RetOrErr) {
     250          40 :     consumeError(RetOrErr.takeError());
     251             :   }
     252          40 : };
     253             : 
     254          64 : // ResultTraits specialization for void functions.
     255          56 : template <> class ResultTraits<void> {
     256          40 : public:
     257             :   // For void functions, ErrorReturnType is llvm::Error.
     258           0 :   using ErrorReturnType = Error;
     259             : 
     260           0 : #ifdef _MSC_VER
     261             :   // The ErrorReturnType wrapped in a std::promise.
     262           0 :   using ReturnPromiseType = std::promise<MSVCPError>;
     263           0 : 
     264           0 :   // The ErrorReturnType wrapped in a std::future.
     265             :   using ReturnFutureType = std::future<MSVCPError>;
     266          24 : #else
     267             :   // The ErrorReturnType wrapped in a std::promise.
     268          57 :   using ReturnPromiseType = std::promise<ErrorReturnType>;
     269             : 
     270          48 :   // The ErrorReturnType wrapped in a std::future.
     271          24 :   using ReturnFutureType = std::future<ErrorReturnType>;
     272          24 : #endif
     273             : 
     274         130 :   // Create a 'blank' value of the ErrorReturnType, ready and safe to
     275           2 :   // overwrite.
     276         130 :   static ErrorReturnType createBlankErrorReturnValue() {
     277             :     return ErrorReturnType::success();
     278          96 :   }
     279          48 : 
     280         130 :   // Consume an abandoned ErrorReturnType.
     281             :   static void consumeAbandoned(ErrorReturnType Err) {
     282         130 :     consumeError(std::move(Err));
     283             :   }
     284         130 : };
     285             : 
     286          96 : // ResultTraits<Error> is equivalent to ResultTraits<void>. This allows
     287          72 : // handlers for void RPC functions to return either void (in which case they
     288         130 : // implicitly succeed) or Error (in which case their error return is
     289             : // propagated). See usage in HandlerTraits::runHandlerHelper.
     290         136 : template <> class ResultTraits<Error> : public ResultTraits<void> {};
     291             : 
     292         152 : // ResultTraits<Expected<T>> is equivalent to ResultTraits<T>. This allows
     293             : // handlers for RPC functions returning a T to return either a T (in which
     294          96 : // case they implicitly succeed) or Expected<T> (in which case their error
     295          96 : // return is propagated). See usage in HandlerTraits::runHandlerHelper.
     296         136 : template <typename RetT>
     297             : class ResultTraits<Expected<RetT>> : public ResultTraits<RetT> {};
     298          24 : 
     299          96 : // Determines whether an RPC function's defined error return type supports
     300          24 : // error return value.
     301             : template <typename T>
     302          48 : class SupportsErrorReturn {
     303          24 : public:
     304          24 :   static const bool value = false;
     305             : };
     306          24 : 
     307             : template <>
     308          24 : class SupportsErrorReturn<Error> {
     309             : public:
     310          48 :   static const bool value = true;
     311          24 : };
     312          24 : 
     313             : template <typename T>
     314          24 : class SupportsErrorReturn<Expected<T>> {
     315             : public:
     316          24 :   static const bool value = true;
     317             : };
     318          48 : 
     319          24 : // RespondHelper packages return values based on whether or not the declared
     320          24 : // RPC function return type supports error returns.
     321           0 : template <bool FuncSupportsErrorReturn>
     322          24 : class RespondHelper;
     323           0 : 
     324          24 : // RespondHelper specialization for functions that support error returns.
     325             : template <>
     326          48 : class RespondHelper<true> {
     327          48 : public:
     328          24 : 
     329             :   // Send Expected<T>.
     330          24 :   template <typename WireRetT, typename HandlerRetT, typename ChannelT,
     331             :             typename FunctionIdT, typename SequenceNumberT>
     332          48 :   static Error sendResult(ChannelT &C, const FunctionIdT &ResponseId,
     333             :                           SequenceNumberT SeqNo,
     334          48 :                           Expected<HandlerRetT> ResultOrErr) {
     335          24 :     if (!ResultOrErr && ResultOrErr.template errorIsA<RPCFatalError>())
     336          24 :       return ResultOrErr.takeError();
     337             : 
     338          24 :     // Open the response message.
     339          24 :     if (auto Err = C.startSendMessage(ResponseId, SeqNo))
     340          24 :       return Err;
     341             : 
     342          48 :     // Serialize the result.
     343          24 :     if (auto Err =
     344          24 :         SerializationTraits<ChannelT, WireRetT,
     345           0 :                             Expected<HandlerRetT>>::serialize(
     346           0 :                                                      C, std::move(ResultOrErr)))
     347           0 :       return Err;
     348           0 : 
     349           0 :     // Close the response message.
     350           0 :     return C.endSendMessage();
     351           0 :   }
     352           0 : 
     353           0 :   template <typename ChannelT, typename FunctionIdT, typename SequenceNumberT>
     354           0 :   static Error sendResult(ChannelT &C, const FunctionIdT &ResponseId,
     355           0 :                           SequenceNumberT SeqNo, Error Err) {
     356           0 :     if (Err && Err.isA<RPCFatalError>())
     357             :       return Err;
     358             :     if (auto Err2 = C.startSendMessage(ResponseId, SeqNo))
     359             :       return Err2;
     360             :     if (auto Err2 = serializeSeq(C, std::move(Err)))
     361             :       return Err2;
     362             :     return C.endSendMessage();
     363             :   }
     364             : 
     365             : };
     366             : 
     367             : // RespondHelper specialization for functions that do not support error returns.
     368             : template <>
     369             : class RespondHelper<false> {
     370             : public:
     371             : 
     372             :   template <typename WireRetT, typename HandlerRetT, typename ChannelT,
     373             :             typename FunctionIdT, typename SequenceNumberT>
     374             :   static Error sendResult(ChannelT &C, const FunctionIdT &ResponseId,
     375             :                           SequenceNumberT SeqNo,
     376             :                           Expected<HandlerRetT> ResultOrErr) {
     377             :     if (auto Err = ResultOrErr.takeError())
     378             :       return Err;
     379             : 
     380          24 :     // Open the response message.
     381          24 :     if (auto Err = C.startSendMessage(ResponseId, SeqNo))
     382             :       return Err;
     383             : 
     384             :     // Serialize the result.
     385           0 :     if (auto Err =
     386           0 :         SerializationTraits<ChannelT, WireRetT, HandlerRetT>::serialize(
     387         480 :                                                                C, *ResultOrErr))
     388           0 :       return Err;
     389           0 : 
     390           0 :     // Close the response message.
     391           0 :     return C.endSendMessage();
     392           0 :   }
     393           0 : 
     394           0 :   template <typename ChannelT, typename FunctionIdT, typename SequenceNumberT>
     395           0 :   static Error sendResult(ChannelT &C, const FunctionIdT &ResponseId,
     396           0 :                           SequenceNumberT SeqNo, Error Err) {
     397           0 :     if (Err)
     398           0 :       return Err;
     399           0 :     if (auto Err2 = C.startSendMessage(ResponseId, SeqNo))
     400           0 :       return Err2;
     401           0 :     return C.endSendMessage();
     402           0 :   }
     403           0 : 
     404           2 : };
     405           0 : 
     406             : 
     407           2 : // Send a response of the given wire return type (WireRetT) over the
     408             : // channel, with the given sequence number.
     409             : template <typename WireRetT, typename HandlerRetT, typename ChannelT,
     410             :           typename FunctionIdT, typename SequenceNumberT>
     411           4 : Error respond(ChannelT &C, const FunctionIdT &ResponseId,
     412             :               SequenceNumberT SeqNo, Expected<HandlerRetT> ResultOrErr) {
     413             :   return RespondHelper<SupportsErrorReturn<WireRetT>::value>::
     414             :     template sendResult<WireRetT>(C, ResponseId, SeqNo, std::move(ResultOrErr));
     415           4 : }
     416             : 
     417             : // Send an empty response message on the given channel to indicate that
     418             : // the handler ran.
     419             : template <typename WireRetT, typename ChannelT, typename FunctionIdT,
     420             :           typename SequenceNumberT>
     421             : Error respond(ChannelT &C, const FunctionIdT &ResponseId, SequenceNumberT SeqNo,
     422             :               Error Err) {
     423             :   return RespondHelper<SupportsErrorReturn<WireRetT>::value>::
     424             :     sendResult(C, ResponseId, SeqNo, std::move(Err));
     425             : }
     426           2 : 
     427             : // Converts a given type to the equivalent error return type.
     428           2 : template <typename T> class WrappedHandlerReturn {
     429             : public:
     430           4 :   using Type = Expected<T>;
     431             : };
     432           2 : 
     433           0 : template <typename T> class WrappedHandlerReturn<Expected<T>> {
     434           0 : public:
     435           0 :   using Type = Expected<T>;
     436           0 : };
     437          15 : 
     438           0 : template <> class WrappedHandlerReturn<void> {
     439           0 : public:
     440          15 :   using Type = Error;
     441           0 : };
     442             : 
     443             : template <> class WrappedHandlerReturn<Error> {
     444          30 : public:
     445             :   using Type = Error;
     446          24 : };
     447             : 
     448          30 : template <> class WrappedHandlerReturn<ErrorSuccess> {
     449          24 : public:
     450             :   using Type = Error;
     451             : };
     452             : 
     453          48 : // Traits class that strips the response function from the list of handler
     454             : // arguments.
     455             : template <typename FnT> class AsyncHandlerTraits;
     456             : 
     457          34 : template <typename ResultT, typename... ArgTs>
     458             : class AsyncHandlerTraits<Error(std::function<Error(Expected<ResultT>)>, ArgTs...)> {
     459             : public:
     460          10 :   using Type = Error(ArgTs...);
     461             :   using ResultType = Expected<ResultT>;
     462             : };
     463             : 
     464          20 : template <typename... ArgTs>
     465           6 : class AsyncHandlerTraits<Error(std::function<Error(Error)>, ArgTs...)> {
     466             : public:
     467             :   using Type = Error(ArgTs...);
     468          26 :   using ResultType = Error;
     469             : };
     470             : 
     471             : template <typename... ArgTs>
     472          12 : class AsyncHandlerTraits<ErrorSuccess(std::function<Error(Error)>, ArgTs...)> {
     473             : public:
     474             :   using Type = Error(ArgTs...);
     475             :   using ResultType = Error;
     476           6 : };
     477           5 : 
     478             : template <typename... ArgTs>
     479             : class AsyncHandlerTraits<void(std::function<Error(Error)>, ArgTs...)> {
     480           5 : public:
     481             :   using Type = Error(ArgTs...);
     482             :   using ResultType = Error;
     483             : };
     484          28 : 
     485             : template <typename ResponseHandlerT, typename... ArgTs>
     486             : class AsyncHandlerTraits<Error(ResponseHandlerT, ArgTs...)> :
     487          18 :     public AsyncHandlerTraits<Error(typename std::decay<ResponseHandlerT>::type,
     488          10 :                                     ArgTs...)> {};
     489             : 
     490             : // This template class provides utilities related to RPC function handlers.
     491          36 : // The base case applies to non-function types (the template class is
     492             : // specialized for function types) and inherits from the appropriate
     493             : // speciilization for the given non-function type's call operator.
     494             : template <typename HandlerT>
     495          18 : class HandlerTraits : public HandlerTraits<decltype(
     496             :                           &std::remove_reference<HandlerT>::type::operator())> {
     497             : };
     498             : 
     499           4 : // Traits for handlers with a given function type.
     500             : template <typename RetT, typename... ArgTs>
     501           4 : class HandlerTraits<RetT(ArgTs...)> {
     502             : public:
     503           8 :   // Function type of the handler.
     504             :   using Type = RetT(ArgTs...);
     505          12 : 
     506             :   // Return type of the handler.
     507           8 :   using ReturnType = RetT;
     508             : 
     509          16 :   // Call the given handler with the given arguments.
     510             :   template <typename HandlerT, typename... TArgTs>
     511             :   static typename WrappedHandlerReturn<RetT>::Type
     512             :   unpackAndRun(HandlerT &Handler, std::tuple<TArgTs...> &Args) {
     513             :     return unpackAndRunHelper(Handler, Args,
     514             :                               llvm::index_sequence_for<TArgTs...>());
     515             :   }
     516             : 
     517             :   // Call the given handler with the given arguments.
     518             :   template <typename HandlerT, typename ResponderT, typename... TArgTs>
     519          24 :   static Error unpackAndRunAsync(HandlerT &Handler, ResponderT &Responder,
     520             :                                  std::tuple<TArgTs...> &Args) {
     521          26 :     return unpackAndRunAsyncHelper(Handler, Responder, Args,
     522          24 :                                    llvm::index_sequence_for<TArgTs...>());
     523             :   }
     524          26 : 
     525             :   // Call the given handler with the given arguments.
     526          50 :   template <typename HandlerT>
     527             :   static typename std::enable_if<
     528           0 :       std::is_void<typename HandlerTraits<HandlerT>::ReturnType>::value,
     529           2 :       Error>::type
     530          24 :   run(HandlerT &Handler, ArgTs &&... Args) {
     531           6 :     Handler(std::move(Args)...);
     532             :     return Error::success();
     533             :   }
     534           6 : 
     535           0 :   template <typename HandlerT, typename... TArgTs>
     536          18 :   static typename std::enable_if<
     537             :       !std::is_void<typename HandlerTraits<HandlerT>::ReturnType>::value,
     538             :       typename HandlerTraits<HandlerT>::ReturnType>::type
     539          18 :   run(HandlerT &Handler, TArgTs... Args) {
     540           8 :     return Handler(std::move(Args)...);
     541             :   }
     542           8 : 
     543             :   // Serialize arguments to the channel.
     544          16 :   template <typename ChannelT, typename... CArgTs>
     545             :   static Error serializeArgs(ChannelT &C, const CArgTs... CArgs) {
     546          10 :     return SequenceSerialization<ChannelT, ArgTs...>::serialize(C, CArgs...);
     547           0 :   }
     548             : 
     549          10 :   // Deserialize arguments from the channel.
     550           0 :   template <typename ChannelT, typename... CArgTs>
     551           2 :   static Error deserializeArgs(ChannelT &C, std::tuple<CArgTs...> &Args) {
     552             :     return deserializeArgsHelper(C, Args,
     553             :                                  llvm::index_sequence_for<CArgTs...>());
     554           2 :   }
     555             : 
     556          41 : private:
     557             :   template <typename ChannelT, typename... CArgTs, size_t... Indexes>
     558           0 :   static Error deserializeArgsHelper(ChannelT &C, std::tuple<CArgTs...> &Args,
     559          41 :                                      llvm::index_sequence<Indexes...> _) {
     560             :     return SequenceSerialization<ChannelT, ArgTs...>::deserialize(
     561          16 :         C, std::get<Indexes>(Args)...);
     562             :   }
     563             : 
     564         343 :   template <typename HandlerT, typename ArgTuple, size_t... Indexes>
     565             :   static typename WrappedHandlerReturn<
     566           5 :       typename HandlerTraits<HandlerT>::ReturnType>::Type
     567         327 :   unpackAndRunHelper(HandlerT &Handler, ArgTuple &Args,
     568             :                      llvm::index_sequence<Indexes...>) {
     569           5 :     return run(Handler, std::move(std::get<Indexes>(Args))...);
     570             :   }
     571         678 : 
     572             : 
     573           0 :   template <typename HandlerT, typename ResponderT, typename ArgTuple,
     574          24 :             size_t... Indexes>
     575         327 :   static typename WrappedHandlerReturn<
     576             :       typename HandlerTraits<HandlerT>::ReturnType>::Type
     577           0 :   unpackAndRunAsyncHelper(HandlerT &Handler, ResponderT &Responder,
     578             :                           ArgTuple &Args,
     579             :                           llvm::index_sequence<Indexes...>) {
     580             :     return run(Handler, Responder, std::move(std::get<Indexes>(Args))...);
     581          12 :   }
     582             : };
     583          24 : 
     584          12 : // Handler traits for free functions.
     585             : template <typename RetT, typename... ArgTs>
     586          28 : class HandlerTraits<RetT(*)(ArgTs...)>
     587             :   : public HandlerTraits<RetT(ArgTs...)> {};
     588             : 
     589           4 : // Handler traits for class methods (especially call operators for lambdas).
     590          48 : template <typename Class, typename RetT, typename... ArgTs>
     591           8 : class HandlerTraits<RetT (Class::*)(ArgTs...)>
     592             :     : public HandlerTraits<RetT(ArgTs...)> {};
     593             : 
     594          32 : // Handler traits for const class methods (especially call operators for
     595             : // lambdas).
     596             : template <typename Class, typename RetT, typename... ArgTs>
     597             : class HandlerTraits<RetT (Class::*)(ArgTs...) const>
     598             :     : public HandlerTraits<RetT(ArgTs...)> {};
     599             : 
     600             : // Utility to peel the Expected wrapper off a response handler error type.
     601             : template <typename HandlerT> class ResponseHandlerArg;
     602           0 : 
     603           0 : template <typename ArgT> class ResponseHandlerArg<Error(Expected<ArgT>)> {
     604             : public:
     605           0 :   using ArgType = Expected<ArgT>;
     606           0 :   using UnwrappedArgType = ArgT;
     607             : };
     608           0 : 
     609           0 : template <typename ArgT>
     610             : class ResponseHandlerArg<ErrorSuccess(Expected<ArgT>)> {
     611           0 : public:
     612             :   using ArgType = Expected<ArgT>;
     613           0 :   using UnwrappedArgType = ArgT;
     614             : };
     615             : 
     616           0 : template <> class ResponseHandlerArg<Error(Error)> {
     617             : public:
     618             :   using ArgType = Error;
     619             : };
     620             : 
     621           0 : template <> class ResponseHandlerArg<ErrorSuccess(Error)> {
     622             : public:
     623             :   using ArgType = Error;
     624           0 : };
     625             : 
     626             : // ResponseHandler represents a handler for a not-yet-received function call
     627             : // result.
     628           0 : template <typename ChannelT> class ResponseHandler {
     629             : public:
     630             :   virtual ~ResponseHandler() {}
     631             : 
     632           0 :   // Reads the function result off the wire and acts on it. The meaning of
     633             :   // "act" will depend on how this method is implemented in any given
     634             :   // ResponseHandler subclass but could, for example, mean running a
     635             :   // user-specified handler or setting a promise value.
     636             :   virtual Error handleResponse(ChannelT &C) = 0;
     637             : 
     638             :   // Abandons this outstanding result.
     639             :   virtual void abandon() = 0;
     640          78 : 
     641             :   // Create an error instance representing an abandoned response.
     642             :   static Error createAbandonedResponseError() {
     643          78 :     return make_error<ResponseAbandoned>();
     644             :   }
     645             : };
     646             : 
     647         156 : // ResponseHandler subclass for RPC functions with non-void returns.
     648             : template <typename ChannelT, typename FuncRetT, typename HandlerT>
     649             : class ResponseHandlerImpl : public ResponseHandler<ChannelT> {
     650             : public:
     651          78 :   ResponseHandlerImpl(HandlerT Handler) : Handler(std::move(Handler)) {}
     652           0 : 
     653             :   // Handle the result by deserializing it from the channel then passing it
     654           0 :   // to the user defined handler.
     655             :   Error handleResponse(ChannelT &C) override {
     656           0 :     using UnwrappedArgType = typename ResponseHandlerArg<
     657             :         typename HandlerTraits<HandlerT>::Type>::UnwrappedArgType;
     658           0 :     UnwrappedArgType Result;
     659           0 :     if (auto Err =
     660           0 :             SerializationTraits<ChannelT, FuncRetT,
     661             :                                 UnwrappedArgType>::deserialize(C, Result))
     662           0 :       return Err;
     663             :     if (auto Err = C.endReceiveMessage())
     664           0 :       return Err;
     665             :     return Handler(std::move(Result));
     666           0 :   }
     667             : 
     668           0 :   // Abandon this response by calling the handler with an 'abandoned response'
     669             :   // error.
     670           0 :   void abandon() override {
     671             :     if (auto Err = Handler(this->createAbandonedResponseError())) {
     672           0 :       // Handlers should not fail when passed an abandoned response error.
     673             :       report_fatal_error(std::move(Err));
     674           0 :     }
     675             :   }
     676           0 : 
     677             : private:
     678          24 :   HandlerT Handler;
     679             : };
     680           0 : 
     681          24 : // ResponseHandler subclass for RPC functions with void returns.
     682           0 : template <typename ChannelT, typename HandlerT>
     683             : class ResponseHandlerImpl<ChannelT, void, HandlerT>
     684           0 :     : public ResponseHandler<ChannelT> {
     685          48 : public:
     686           0 :   ResponseHandlerImpl(HandlerT Handler) : Handler(std::move(Handler)) {}
     687             : 
     688           0 :   // Handle the result (no actual value, just a notification that the function
     689          24 :   // has completed on the remote end) by calling the user-defined handler with
     690           0 :   // Error::success().
     691             :   Error handleResponse(ChannelT &C) override {
     692           0 :     if (auto Err = C.endReceiveMessage())
     693             :       return Err;
     694           0 :     return Handler(Error::success());
     695             :   }
     696           0 : 
     697         201 :   // Abandon this response by calling the handler with an 'abandoned response'
     698           0 :   // error.
     699             :   void abandon() override {
     700         201 :     if (auto Err = Handler(this->createAbandonedResponseError())) {
     701             :       // Handlers should not fail when passed an abandoned response error.
     702           0 :       report_fatal_error(std::move(Err));
     703             :     }
     704         402 :   }
     705             : 
     706           0 : private:
     707             :   HandlerT Handler;
     708         201 : };
     709             : 
     710           0 : template <typename ChannelT, typename FuncRetT, typename HandlerT>
     711           0 : class ResponseHandlerImpl<ChannelT, Expected<FuncRetT>, HandlerT>
     712           0 :     : public ResponseHandler<ChannelT> {
     713             : public:
     714           0 :   ResponseHandlerImpl(HandlerT Handler) : Handler(std::move(Handler)) {}
     715             : 
     716           0 :   // Handle the result by deserializing it from the channel then passing it
     717             :   // to the user defined handler.
     718         199 :   Error handleResponse(ChannelT &C) override {
     719           0 :     using HandlerArgType = typename ResponseHandlerArg<
     720         199 :         typename HandlerTraits<HandlerT>::Type>::ArgType;
     721           0 :     HandlerArgType Result((typename HandlerArgType::value_type()));
     722         398 : 
     723             :     if (auto Err =
     724           0 :             SerializationTraits<ChannelT, Expected<FuncRetT>,
     725             :                                 HandlerArgType>::deserialize(C, Result))
     726             :       return Err;
     727             :     if (auto Err = C.endReceiveMessage())
     728             :       return Err;
     729             :     return Handler(std::move(Result));
     730             :   }
     731             : 
     732           0 :   // Abandon this response by calling the handler with an 'abandoned response'
     733           0 :   // error.
     734         327 :   void abandon() override {
     735             :     if (auto Err = Handler(this->createAbandonedResponseError())) {
     736           0 :       // Handlers should not fail when passed an abandoned response error.
     737         327 :       report_fatal_error(std::move(Err));
     738           0 :     }
     739          24 :   }
     740           0 : 
     741           0 : private:
     742          24 :   HandlerT Handler;
     743             : };
     744           0 : 
     745             : template <typename ChannelT, typename HandlerT>
     746           0 : class ResponseHandlerImpl<ChannelT, Error, HandlerT>
     747           0 :     : public ResponseHandler<ChannelT> {
     748          28 : public:
     749           0 :   ResponseHandlerImpl(HandlerT Handler) : Handler(std::move(Handler)) {}
     750           0 : 
     751           0 :   // Handle the result by deserializing it from the channel then passing it
     752           0 :   // to the user defined handler.
     753           0 :   Error handleResponse(ChannelT &C) override {
     754          78 :     Error Result = Error::success();
     755           0 :     if (auto Err =
     756           0 :             SerializationTraits<ChannelT, Error, Error>::deserialize(C, Result))
     757          78 :       return Err;
     758           0 :     if (auto Err = C.endReceiveMessage())
     759           0 :       return Err;
     760           0 :     return Handler(std::move(Result));
     761           0 :   }
     762           0 : 
     763           0 :   // Abandon this response by calling the handler with an 'abandoned response'
     764          24 :   // error.
     765           0 :   void abandon() override {
     766           0 :     if (auto Err = Handler(this->createAbandonedResponseError())) {
     767          24 :       // Handlers should not fail when passed an abandoned response error.
     768           0 :       report_fatal_error(std::move(Err));
     769         201 :     }
     770           0 :   }
     771             : 
     772         201 : private:
     773           0 :   HandlerT Handler;
     774           0 : };
     775           0 : 
     776             : // Create a ResponseHandler from a given user handler.
     777           2 : template <typename ChannelT, typename FuncRetT, typename HandlerT>
     778           5 : std::unique_ptr<ResponseHandler<ChannelT>> createResponseHandler(HandlerT H) {
     779         199 :   return llvm::make_unique<ResponseHandlerImpl<ChannelT, FuncRetT, HandlerT>>(
     780           0 :       std::move(H));
     781           0 : }
     782         199 : 
     783           0 : // Helper for wrapping member functions up as functors. This is useful for
     784           0 : // installing methods as result handlers.
     785           0 : template <typename ClassT, typename RetT, typename... ArgTs>
     786           0 : class MemberFnWrapper {
     787           0 : public:
     788           0 :   using MethodT = RetT (ClassT::*)(ArgTs...);
     789           0 :   MemberFnWrapper(ClassT &Instance, MethodT Method)
     790           0 :       : Instance(Instance), Method(Method) {}
     791             :   RetT operator()(ArgTs &&... Args) {
     792           0 :     return (Instance.*Method)(std::move(Args)...);
     793           0 :   }
     794           0 : 
     795           0 : private:
     796           0 :   ClassT &Instance;
     797             :   MethodT Method;
     798           0 : };
     799           0 : 
     800           0 : // Helper that provides a Functor for deserializing arguments.
     801           1 : template <typename... ArgTs> class ReadArgs {
     802           3 : public:
     803           0 :   Error operator()() { return Error::success(); }
     804           0 : };
     805           0 : 
     806             : template <typename ArgT, typename... ArgTs>
     807           1 : class ReadArgs<ArgT, ArgTs...> : public ReadArgs<ArgTs...> {
     808           2 : public:
     809           0 :   ReadArgs(ArgT &Arg, ArgTs &... Args)
     810           0 :       : ReadArgs<ArgTs...>(Args...), Arg(Arg) {}
     811           0 : 
     812             :   Error operator()(ArgT &ArgVal, ArgTs &... ArgVals) {
     813           0 :     this->Arg = std::move(ArgVal);
     814             :     return ReadArgs<ArgTs...>::operator()(ArgVals...);
     815           0 :   }
     816           0 : 
     817           1 : private:
     818             :   ArgT &Arg;
     819           0 : };
     820           0 : 
     821           0 : // Manage sequence numbers.
     822           0 : template <typename SequenceNumberT> class SequenceNumberManager {
     823           0 : public:
     824             :   // Reset, making all sequence numbers available.
     825           0 :   void reset() {
     826           0 :     std::lock_guard<std::mutex> Lock(SeqNoLock);
     827           0 :     NextSequenceNumber = 0;
     828           0 :     FreeSequenceNumbers.clear();
     829           0 :   }
     830             : 
     831           0 :   // Get the next available sequence number. Will re-use numbers that have
     832             :   // been released.
     833           0 :   SequenceNumberT getSequenceNumber() {
     834           0 :     std::lock_guard<std::mutex> Lock(SeqNoLock);
     835           0 :     if (FreeSequenceNumbers.empty())
     836           0 :       return NextSequenceNumber++;
     837           0 :     auto SequenceNumber = FreeSequenceNumbers.back();
     838           0 :     FreeSequenceNumbers.pop_back();
     839           0 :     return SequenceNumber;
     840           0 :   }
     841           0 : 
     842           0 :   // Release a sequence number, making it available for re-use.
     843           0 :   void releaseSequenceNumber(SequenceNumberT SequenceNumber) {
     844           0 :     std::lock_guard<std::mutex> Lock(SeqNoLock);
     845           0 :     FreeSequenceNumbers.push_back(SequenceNumber);
     846           0 :   }
     847           0 : 
     848           0 : private:
     849           0 :   std::mutex SeqNoLock;
     850           0 :   SequenceNumberT NextSequenceNumber = 0;
     851           0 :   std::vector<SequenceNumberT> FreeSequenceNumbers;
     852           0 : };
     853           0 : 
     854             : // Checks that predicate P holds for each corresponding pair of type arguments
     855           0 : // from T1 and T2 tuple.
     856             : template <template <class, class> class P, typename T1Tuple, typename T2Tuple>
     857           0 : class RPCArgTypeCheckHelper;
     858             : 
     859           0 : template <template <class, class> class P>
     860           0 : class RPCArgTypeCheckHelper<P, std::tuple<>, std::tuple<>> {
     861           0 : public:
     862           0 :   static const bool value = true;
     863           0 : };
     864             : 
     865           0 : template <template <class, class> class P, typename T, typename... Ts,
     866             :           typename U, typename... Us>
     867           0 : class RPCArgTypeCheckHelper<P, std::tuple<T, Ts...>, std::tuple<U, Us...>> {
     868             : public:
     869           0 :   static const bool value =
     870           0 :       P<T, U>::value &&
     871           0 :       RPCArgTypeCheckHelper<P, std::tuple<Ts...>, std::tuple<Us...>>::value;
     872           0 : };
     873           0 : 
     874           0 : template <template <class, class> class P, typename T1Sig, typename T2Sig>
     875           0 : class RPCArgTypeCheck {
     876           0 : public:
     877           0 :   using T1Tuple = typename FunctionArgsTuple<T1Sig>::Type;
     878           0 :   using T2Tuple = typename FunctionArgsTuple<T2Sig>::Type;
     879             : 
     880         327 :   static_assert(std::tuple_size<T1Tuple>::value >=
     881             :                     std::tuple_size<T2Tuple>::value,
     882           0 :                 "Too many arguments to RPC call");
     883             :   static_assert(std::tuple_size<T1Tuple>::value <=
     884         327 :                     std::tuple_size<T2Tuple>::value,
     885           0 :                 "Too few arguments to RPC call");
     886             : 
     887           0 :   static const bool value = RPCArgTypeCheckHelper<P, T1Tuple, T2Tuple>::value;
     888         630 : };
     889             : 
     890           0 : template <typename ChannelT, typename WireT, typename ConcreteT>
     891             : class CanSerialize {
     892           0 : private:
     893             :   using S = SerializationTraits<ChannelT, WireT, ConcreteT>;
     894         630 : 
     895           0 :   template <typename T>
     896          24 :   static std::true_type
     897           0 :   check(typename std::enable_if<
     898             :         std::is_same<decltype(T::serialize(std::declval<ChannelT &>(),
     899             :                                            std::declval<const ConcreteT &>())),
     900          48 :                      Error>::value,
     901             :         void *>::type);
     902           0 : 
     903             :   template <typename> static std::false_type check(...);
     904             : 
     905           0 : public:
     906          48 :   static const bool value = decltype(check<S>(0))::value;
     907             : };
     908           0 : 
     909             : template <typename ChannelT, typename WireT, typename ConcreteT>
     910           0 : class CanDeserialize {
     911           0 : private:
     912           0 :   using S = SerializationTraits<ChannelT, WireT, ConcreteT>;
     913           0 : 
     914             :   template <typename T>
     915           0 :   static std::true_type
     916             :   check(typename std::enable_if<
     917           0 :         std::is_same<decltype(T::deserialize(std::declval<ChannelT &>(),
     918           0 :                                              std::declval<ConcreteT &>())),
     919           0 :                      Error>::value,
     920          20 :         void *>::type);
     921           0 : 
     922             :   template <typename> static std::false_type check(...);
     923           0 : 
     924          40 : public:
     925           0 :   static const bool value = decltype(check<S>(0))::value;
     926             : };
     927           0 : 
     928             : /// Contains primitive utilities for defining, calling and handling calls to
     929           0 : /// remote procedures. ChannelT is a bidirectional stream conforming to the
     930          40 : /// RPCChannel interface (see RPCChannel.h), FunctionIdT is a procedure
     931           0 : /// identifier type that must be serializable on ChannelT, and SequenceNumberT
     932          24 : /// is an integral type that will be used to number in-flight function calls.
     933           0 : ///
     934             : /// These utilities support the construction of very primitive RPC utilities.
     935           0 : /// Their intent is to ensure correct serialization and deserialization of
     936          24 : /// procedure arguments, and to keep the client and server's view of the API in
     937           0 : /// sync.
     938             : template <typename ImplT, typename ChannelT, typename FunctionIdT,
     939           0 :           typename SequenceNumberT>
     940           0 : class RPCEndpointBase {
     941           0 : protected:
     942          24 :   class OrcRPCInvalid : public Function<OrcRPCInvalid, void()> {
     943           0 :   public:
     944           0 :     static const char *getName() { return "__orc_rpc$invalid"; }
     945           0 :   };
     946             : 
     947           0 :   class OrcRPCResponse : public Function<OrcRPCResponse, void()> {
     948           0 :   public:
     949           0 :     static const char *getName() { return "__orc_rpc$response"; }
     950           0 :   };
     951           0 : 
     952             :   class OrcRPCNegotiate
     953           0 :       : public Function<OrcRPCNegotiate, FunctionIdT(std::string)> {
     954           0 :   public:
     955           0 :     static const char *getName() { return "__orc_rpc$negotiate"; }
     956           0 :   };
     957          24 : 
     958           0 :   // Helper predicate for testing for the presence of SerializeTraits
     959           0 :   // serializers.
     960           0 :   template <typename WireT, typename ConcreteT>
     961          24 :   class CanSerializeCheck : detail::CanSerialize<ChannelT, WireT, ConcreteT> {
     962             :   public:
     963           0 :     using detail::CanSerialize<ChannelT, WireT, ConcreteT>::value;
     964             : 
     965          48 :     static_assert(value, "Missing serializer for argument (Can't serialize the "
     966           0 :                          "first template type argument of CanSerializeCheck "
     967           0 :                          "from the second)");
     968           0 :   };
     969           0 : 
     970           0 :   // Helper predicate for testing for the presence of SerializeTraits
     971          48 :   // deserializers.
     972           0 :   template <typename WireT, typename ConcreteT>
     973           0 :   class CanDeserializeCheck
     974             :       : detail::CanDeserialize<ChannelT, WireT, ConcreteT> {
     975           0 :   public:
     976           0 :     using detail::CanDeserialize<ChannelT, WireT, ConcreteT>::value;
     977           0 : 
     978           0 :     static_assert(value, "Missing deserializer for argument (Can't deserialize "
     979           0 :                          "the second template type argument of "
     980          58 :                          "CanDeserializeCheck from the first)");
     981           0 :   };
     982             : 
     983           0 : public:
     984         116 :   /// Construct an RPC instance on a channel.
     985           0 :   RPCEndpointBase(ChannelT &C, bool LazyAutoNegotiation)
     986             :       : C(C), LazyAutoNegotiation(LazyAutoNegotiation) {
     987             :     // Hold ResponseId in a special variable, since we expect Response to be
     988           0 :     // called relatively frequently, and want to avoid the map lookup.
     989             :     ResponseId = FnIdAllocator.getResponseId();
     990         116 :     RemoteFunctionIds[OrcRPCResponse::getPrototype()] = ResponseId;
     991             : 
     992         209 :     // Register the negotiate function id and handler.
     993           0 :     auto NegotiateId = FnIdAllocator.getNegotiateId();
     994             :     RemoteFunctionIds[OrcRPCNegotiate::getPrototype()] = NegotiateId;
     995           0 :     Handlers[NegotiateId] = wrapHandler<OrcRPCNegotiate>(
     996         402 :         [this](const std::string &Name) { return handleNegotiate(Name); });
     997           8 :   }
     998           0 : 
     999             : 
    1000           8 :   /// Negotiate a function id for Func with the other end of the channel.
    1001           0 :   template <typename Func> Error negotiateFunction(bool Retry = false) {
    1002         402 :     return getRemoteFunctionId<Func>(true, Retry).takeError();
    1003           0 :   }
    1004             : 
    1005           0 :   /// Append a call Func, does not call send on the channel.
    1006           0 :   /// The first argument specifies a user-defined handler to be run when the
    1007           0 :   /// function returns. The handler should take an Expected<Func::ReturnType>,
    1008           0 :   /// or an Error (if Func::ReturnType is void). The handler will be called
    1009             :   /// with an error if the return value is abandoned due to a channel error.
    1010           0 :   template <typename Func, typename HandlerT, typename... ArgTs>
    1011           0 :   Error appendCallAsync(HandlerT Handler, const ArgTs &... Args) {
    1012           0 : 
    1013           0 :     static_assert(
    1014           0 :         detail::RPCArgTypeCheck<CanSerializeCheck, typename Func::Type,
    1015           0 :                                 void(ArgTs...)>::value,
    1016             :         "");
    1017             : 
    1018           0 :     // Look up the function ID.
    1019           0 :     FunctionIdT FnId;
    1020          15 :     if (auto FnIdOrErr = getRemoteFunctionId<Func>(LazyAutoNegotiation, false))
    1021             :       FnId = *FnIdOrErr;
    1022             :     else {
    1023             :       // Negotiation failed. Notify the handler then return the negotiate-failed
    1024          35 :       // error.
    1025           0 :       cantFail(Handler(make_error<ResponseAbandoned>()));
    1026          20 :       return FnIdOrErr.takeError();
    1027             :     }
    1028           0 : 
    1029          30 :     SequenceNumberT SeqNo; // initialized in locked scope below.
    1030           0 :     {
    1031           0 :       // Lock the pending responses map and sequence number manager.
    1032          20 :       std::lock_guard<std::mutex> Lock(ResponsesMutex);
    1033             : 
    1034          20 :       // Allocate a sequence number.
    1035          30 :       SeqNo = SequenceNumberMgr.getSequenceNumber();
    1036           0 :       assert(!PendingResponses.count(SeqNo) &&
    1037           8 :              "Sequence number already allocated");
    1038           0 : 
    1039             :       // Install the user handler.
    1040           0 :       PendingResponses[SeqNo] =
    1041             :         detail::createResponseHandler<ChannelT, typename Func::ReturnType>(
    1042          16 :             std::move(Handler));
    1043           0 :     }
    1044           0 : 
    1045             :     // Open the function call message.
    1046           0 :     if (auto Err = C.startSendMessage(FnId, SeqNo)) {
    1047             :       abandonPendingResponses();
    1048          16 :       return Err;
    1049           0 :     }
    1050           3 : 
    1051             :     // Serialize the call arguments.
    1052           0 :     if (auto Err = detail::HandlerTraits<typename Func::Type>::serializeArgs(
    1053             :             C, Args...)) {
    1054           0 :       abandonPendingResponses();
    1055           6 :       return Err;
    1056           0 :     }
    1057             : 
    1058           0 :     // Close the function call messagee.
    1059             :     if (auto Err = C.endSendMessage()) {
    1060           0 :       abandonPendingResponses();
    1061           6 :       return Err;
    1062           0 :     }
    1063           2 : 
    1064           0 :     return Error::success();
    1065             :   }
    1066           0 : 
    1067             :   Error sendAppendedCalls() { return C.send(); };
    1068           4 : 
    1069             :   template <typename Func, typename HandlerT, typename... ArgTs>
    1070           0 :   Error callAsync(HandlerT Handler, const ArgTs &... Args) {
    1071             :     if (auto Err = appendCallAsync<Func>(std::move(Handler), Args...))
    1072           0 :       return Err;
    1073             :     return C.send();
    1074           4 :   }
    1075             : 
    1076           0 :   /// Handle one incoming call.
    1077         199 :   Error handleOne() {
    1078           0 :     FunctionIdT FnId;
    1079             :     SequenceNumberT SeqNo;
    1080           0 :     if (auto Err = C.startReceiveMessage(FnId, SeqNo)) {
    1081           0 :       abandonPendingResponses();
    1082         220 :       return Err;
    1083             :     }
    1084           0 :     if (FnId == ResponseId)
    1085         199 :       return handleResponse(SeqNo);
    1086          26 :     auto I = Handlers.find(FnId);
    1087           0 :     if (I != Handlers.end())
    1088             :       return I->second(C, SeqNo);
    1089           0 : 
    1090          48 :     // else: No handler found. Report error to client?
    1091             :     return make_error<BadFunctionCall<FunctionIdT, SequenceNumberT>>(FnId,
    1092          24 :                                                                      SeqNo);
    1093             :   }
    1094           0 : 
    1095          24 :   /// Helper for handling setter procedures - this method returns a functor that
    1096          47 :   /// sets the variables referred to by Args... to values deserialized from the
    1097           0 :   /// channel.
    1098           1 :   /// E.g.
    1099             :   ///
    1100           0 :   ///   typedef Function<0, bool, int> Func1;
    1101             :   ///
    1102           4 :   ///   ...
    1103             :   ///   bool B;
    1104             :   ///   int I;
    1105           0 :   ///   if (auto Err = expect<Func1>(Channel, readArgs(B, I)))
    1106             :   ///     /* Handle Args */ ;
    1107          28 :   ///
    1108           1 :   template <typename... ArgTs>
    1109             :   static detail::ReadArgs<ArgTs...> readArgs(ArgTs &... Args) {
    1110          25 :     return detail::ReadArgs<ArgTs...>(Args...);
    1111             :   }
    1112           5 : 
    1113           4 :   /// Abandon all outstanding result handlers.
    1114           2 :   ///
    1115           5 :   /// This will call all currently registered result handlers to receive an
    1116             :   /// "abandoned" error as their argument. This is used internally by the RPC
    1117          24 :   /// in error situations, but can also be called directly by clients who are
    1118           0 :   /// disconnecting from the remote and don't or can't expect responses to their
    1119           0 :   /// outstanding calls. (Especially for outstanding blocking calls, calling
    1120          25 :   /// this function may be necessary to avoid dead threads).
    1121             :   void abandonPendingResponses() {
    1122           1 :     // Lock the pending responses map and sequence number manager.
    1123           0 :     std::lock_guard<std::mutex> Lock(ResponsesMutex);
    1124           0 : 
    1125           0 :     for (auto &KV : PendingResponses)
    1126           2 :       KV.second->abandon();
    1127          58 :     PendingResponses.clear();
    1128             :     SequenceNumberMgr.reset();
    1129           0 :   }
    1130          58 : 
    1131           0 :   /// Remove the handler for the given function.
    1132          65 :   /// A handler must currently be registered for this function.
    1133             :   template <typename Func>
    1134           1 :   void removeHandler() {
    1135          64 :     auto IdItr = LocalFunctionIds.find(Func::getPrototype());
    1136           0 :     assert(IdItr != LocalFunctionIds.end() &&
    1137           0 :            "Function does not have a registered handler");
    1138             :     auto HandlerItr = Handlers.find(IdItr->second);
    1139             :     assert(HandlerItr != Handlers.end() &&
    1140           0 :            "Function does not have a registered handler");
    1141           0 :     Handlers.erase(HandlerItr);
    1142           0 :   }
    1143           0 : 
    1144           1 :   /// Clear all handlers.
    1145           0 :   void clearHandlers() {
    1146           1 :     Handlers.clear();
    1147           0 :   }
    1148           0 : 
    1149           0 : protected:
    1150           0 : 
    1151           0 :   FunctionIdT getInvalidFunctionId() const {
    1152           0 :     return FnIdAllocator.getInvalidId();
    1153           0 :   }
    1154           0 : 
    1155           0 :   /// Add the given handler to the handler map and make it available for
    1156           1 :   /// autonegotiation and execution.
    1157           0 :   template <typename Func, typename HandlerT>
    1158           1 :   void addHandlerImpl(HandlerT Handler) {
    1159           0 : 
    1160             :     static_assert(detail::RPCArgTypeCheck<
    1161             :                       CanDeserializeCheck, typename Func::Type,
    1162           2 :                       typename detail::HandlerTraits<HandlerT>::Type>::value,
    1163           0 :                   "");
    1164           0 : 
    1165             :     FunctionIdT NewFnId = FnIdAllocator.template allocate<Func>();
    1166             :     LocalFunctionIds[Func::getPrototype()] = NewFnId;
    1167             :     Handlers[NewFnId] = wrapHandler<Func>(std::move(Handler));
    1168           2 :   }
    1169           4 : 
    1170           1 :   template <typename Func, typename HandlerT>
    1171             :   void addAsyncHandlerImpl(HandlerT Handler) {
    1172           0 : 
    1173           4 :     static_assert(detail::RPCArgTypeCheck<
    1174           2 :                       CanDeserializeCheck, typename Func::Type,
    1175           8 :                       typename detail::AsyncHandlerTraits<
    1176           0 :                         typename detail::HandlerTraits<HandlerT>::Type
    1177             :                       >::Type>::value,
    1178             :                   "");
    1179             : 
    1180           6 :     FunctionIdT NewFnId = FnIdAllocator.template allocate<Func>();
    1181           0 :     LocalFunctionIds[Func::getPrototype()] = NewFnId;
    1182           3 :     Handlers[NewFnId] = wrapAsyncHandler<Func>(std::move(Handler));
    1183             :   }
    1184           4 : 
    1185             :   Error handleResponse(SequenceNumberT SeqNo) {
    1186           2 :     using Handler = typename decltype(PendingResponses)::mapped_type;
    1187           0 :     Handler PRHandler;
    1188           0 : 
    1189           2 :     {
    1190             :       // Lock the pending responses map and sequence number manager.
    1191           2 :       std::unique_lock<std::mutex> Lock(ResponsesMutex);
    1192           2 :       auto I = PendingResponses.find(SeqNo);
    1193           4 : 
    1194          18 :       if (I != PendingResponses.end()) {
    1195             :         PRHandler = std::move(I->second);
    1196           0 :         PendingResponses.erase(I);
    1197             :         SequenceNumberMgr.releaseSequenceNumber(SeqNo);
    1198          38 :       } else {
    1199           0 :         // Unlock the pending results map to prevent recursive lock.
    1200           0 :         Lock.unlock();
    1201             :         abandonPendingResponses();
    1202           0 :         return make_error<
    1203             :                  InvalidSequenceNumberForResponse<SequenceNumberT>>(SeqNo);
    1204          36 :       }
    1205           0 :     }
    1206           0 : 
    1207           0 :     assert(PRHandler &&
    1208             :            "If we didn't find a response handler we should have bailed out");
    1209           0 : 
    1210           0 :     if (auto Err = PRHandler->handleResponse(C)) {
    1211           0 :       abandonPendingResponses();
    1212           0 :       return Err;
    1213           0 :     }
    1214           0 : 
    1215           0 :     return Error::success();
    1216           0 :   }
    1217           0 : 
    1218           0 :   FunctionIdT handleNegotiate(const std::string &Name) {
    1219           0 :     auto I = LocalFunctionIds.find(Name);
    1220           0 :     if (I == LocalFunctionIds.end())
    1221           0 :       return getInvalidFunctionId();
    1222           0 :     return I->second;
    1223           0 :   }
    1224           0 : 
    1225           0 :   // Find the remote FunctionId for the given function.
    1226           0 :   template <typename Func>
    1227           0 :   Expected<FunctionIdT> getRemoteFunctionId(bool NegotiateIfNotInMap,
    1228           0 :                                             bool NegotiateIfInvalid) {
    1229           0 :     bool DoNegotiate;
    1230           0 : 
    1231           0 :     // Check if we already have a function id...
    1232           0 :     auto I = RemoteFunctionIds.find(Func::getPrototype());
    1233           0 :     if (I != RemoteFunctionIds.end()) {
    1234           0 :       // If it's valid there's nothing left to do.
    1235           0 :       if (I->second != getInvalidFunctionId())
    1236           0 :         return I->second;
    1237             :       DoNegotiate = NegotiateIfInvalid;
    1238           0 :     } else
    1239           0 :       DoNegotiate = NegotiateIfNotInMap;
    1240           0 : 
    1241             :     // We don't have a function id for Func yet, but we're allowed to try to
    1242           0 :     // negotiate one.
    1243             :     if (DoNegotiate) {
    1244           0 :       auto &Impl = static_cast<ImplT &>(*this);
    1245           0 :       if (auto RemoteIdOrErr =
    1246           0 :           Impl.template callB<OrcRPCNegotiate>(Func::getPrototype())) {
    1247             :         RemoteFunctionIds[Func::getPrototype()] = *RemoteIdOrErr;
    1248           0 :         if (*RemoteIdOrErr == getInvalidFunctionId())
    1249             :           return make_error<CouldNotNegotiate>(Func::getPrototype());
    1250           0 :         return *RemoteIdOrErr;
    1251           0 :       } else
    1252           0 :         return RemoteIdOrErr.takeError();
    1253             :     }
    1254           0 : 
    1255             :     // No key was available in the map and we weren't allowed to try to
    1256           8 :     // negotiate one, so return an unknown function error.
    1257          16 :     return make_error<CouldNotNegotiate>(Func::getPrototype());
    1258           0 :   }
    1259           0 : 
    1260           0 :   using WrappedHandlerFn = std::function<Error(ChannelT &, SequenceNumberT)>;
    1261             : 
    1262           0 :   // Wrap the given user handler in the necessary argument-deserialization code,
    1263           0 :   // result-serialization code, and call to the launch policy (if present).
    1264           0 :   template <typename Func, typename HandlerT>
    1265           0 :   WrappedHandlerFn wrapHandler(HandlerT Handler) {
    1266           0 :     return [this, Handler](ChannelT &Channel,
    1267             :                            SequenceNumberT SeqNo) mutable -> Error {
    1268           0 :       // Start by deserializing the arguments.
    1269           0 :       using ArgsTuple =
    1270             :           typename detail::FunctionArgsTuple<
    1271           0 :             typename detail::HandlerTraits<HandlerT>::Type>::Type;
    1272           0 :       auto Args = std::make_shared<ArgsTuple>();
    1273             : 
    1274           8 :       if (auto Err =
    1275          16 :               detail::HandlerTraits<typename Func::Type>::deserializeArgs(
    1276           0 :                   Channel, *Args))
    1277           0 :         return Err;
    1278           0 : 
    1279           3 :       // GCC 4.7 and 4.8 incorrectly issue a -Wunused-but-set-variable warning
    1280             :       // for RPCArgs. Void cast RPCArgs to work around this for now.
    1281             :       // FIXME: Remove this workaround once we can assume a working GCC version.
    1282             :       (void)Args;
    1283             : 
    1284           6 :       // End receieve message, unlocking the channel for reading.
    1285             :       if (auto Err = Channel.endReceiveMessage())
    1286             :         return Err;
    1287           6 : 
    1288             :       using HTraits = detail::HandlerTraits<HandlerT>;
    1289           1 :       using FuncReturn = typename Func::ReturnType;
    1290             :       return detail::respond<FuncReturn>(Channel, ResponseId, SeqNo,
    1291             :                                          HTraits::unpackAndRun(Handler, *Args));
    1292           1 :     };
    1293             :   }
    1294           1 : 
    1295             :   // Wrap the given user handler in the necessary argument-deserialization code,
    1296             :   // result-serialization code, and call to the launch policy (if present).
    1297           1 :   template <typename Func, typename HandlerT>
    1298             :   WrappedHandlerFn wrapAsyncHandler(HandlerT Handler) {
    1299           1 :     return [this, Handler](ChannelT &Channel,
    1300             :                            SequenceNumberT SeqNo) mutable -> Error {
    1301             :       // Start by deserializing the arguments.
    1302           1 :       using AHTraits = detail::AsyncHandlerTraits<
    1303             :                          typename detail::HandlerTraits<HandlerT>::Type>;
    1304           1 :       using ArgsTuple =
    1305             :           typename detail::FunctionArgsTuple<typename AHTraits::Type>::Type;
    1306             :       auto Args = std::make_shared<ArgsTuple>();
    1307           1 : 
    1308          16 :       if (auto Err =
    1309           1 :               detail::HandlerTraits<typename Func::Type>::deserializeArgs(
    1310             :                   Channel, *Args))
    1311           0 :         return Err;
    1312           1 : 
    1313           0 :       // GCC 4.7 and 4.8 incorrectly issue a -Wunused-but-set-variable warning
    1314           1 :       // for RPCArgs. Void cast RPCArgs to work around this for now.
    1315           0 :       // FIXME: Remove this workaround once we can assume a working GCC version.
    1316             :       (void)Args;
    1317           1 : 
    1318             :       // End receieve message, unlocking the channel for reading.
    1319          87 :       if (auto Err = Channel.endReceiveMessage())
    1320          87 :         return Err;
    1321          87 : 
    1322          25 :       using HTraits = detail::HandlerTraits<HandlerT>;
    1323          62 :       using FuncReturn = typename Func::ReturnType;
    1324             :       auto Responder =
    1325          62 :         [this, SeqNo](typename AHTraits::ResultType RetVal) -> Error {
    1326             :           return detail::respond<FuncReturn>(C, ResponseId, SeqNo,
    1327           0 :                                              std::move(RetVal));
    1328           0 :         };
    1329          51 : 
    1330          51 :       return HTraits::unpackAndRunAsync(Handler, Responder, *Args);
    1331          51 :     };
    1332          51 :   }
    1333           0 : 
    1334          24 :   ChannelT &C;
    1335           0 : 
    1336             :   bool LazyAutoNegotiation;
    1337           0 : 
    1338           0 :   RPCFunctionIdAllocator<FunctionIdT> FnIdAllocator;
    1339           0 : 
    1340           0 :   FunctionIdT ResponseId;
    1341           0 :   std::map<std::string, FunctionIdT> LocalFunctionIds;
    1342             :   std::map<const char *, FunctionIdT> RemoteFunctionIds;
    1343             : 
    1344           0 :   std::map<FunctionIdT, WrappedHandlerFn> Handlers;
    1345         546 : 
    1346         526 :   std::mutex ResponsesMutex;
    1347         526 :   detail::SequenceNumberManager<SequenceNumberT> SequenceNumberMgr;
    1348          24 :   std::map<SequenceNumberT, std::unique_ptr<detail::ResponseHandler<ChannelT>>>
    1349         502 :       PendingResponses;
    1350           0 : };
    1351         502 : 
    1352           0 : } // end namespace detail
    1353           0 : 
    1354           0 : template <typename ChannelT, typename FunctionIdT = uint32_t,
    1355         526 :           typename SequenceNumberT = uint32_t>
    1356         526 : class MultiThreadedRPCEndpoint
    1357         526 :     : public detail::RPCEndpointBase<
    1358         526 :           MultiThreadedRPCEndpoint<ChannelT, FunctionIdT, SequenceNumberT>,
    1359           0 :           ChannelT, FunctionIdT, SequenceNumberT> {
    1360           0 : private:
    1361           0 :   using BaseClass =
    1362           0 :       detail::RPCEndpointBase<
    1363           0 :         MultiThreadedRPCEndpoint<ChannelT, FunctionIdT, SequenceNumberT>,
    1364             :         ChannelT, FunctionIdT, SequenceNumberT>;
    1365           0 : 
    1366           0 : public:
    1367             :   MultiThreadedRPCEndpoint(ChannelT &C, bool LazyAutoNegotiation)
    1368             :       : BaseClass(C, LazyAutoNegotiation) {}
    1369             : 
    1370           0 :   /// Add a handler for the given RPC function.
    1371             :   /// This installs the given handler functor for the given RPC Function, and
    1372             :   /// makes the RPC function available for negotiation/calling from the remote.
    1373           0 :   template <typename Func, typename HandlerT>
    1374             :   void addHandler(HandlerT Handler) {
    1375             :     return this->template addHandlerImpl<Func>(std::move(Handler));
    1376             :   }
    1377           2 : 
    1378             :   /// Add a class-method as a handler.
    1379             :   template <typename Func, typename ClassT, typename RetT, typename... ArgTs>
    1380             :   void addHandler(ClassT &Object, RetT (ClassT::*Method)(ArgTs...)) {
    1381             :     addHandler<Func>(
    1382           4 :       detail::MemberFnWrapper<ClassT, RetT, ArgTs...>(Object, Method));
    1383             :   }
    1384             : 
    1385             :   template <typename Func, typename HandlerT>
    1386             :   void addAsyncHandler(HandlerT Handler) {
    1387             :     return this->template addAsyncHandlerImpl<Func>(std::move(Handler));
    1388           3 :   }
    1389             : 
    1390           1 :   /// Add a class-method as a handler.
    1391             :   template <typename Func, typename ClassT, typename RetT, typename... ArgTs>
    1392             :   void addAsyncHandler(ClassT &Object, RetT (ClassT::*Method)(ArgTs...)) {
    1393             :     addAsyncHandler<Func>(
    1394             :       detail::MemberFnWrapper<ClassT, RetT, ArgTs...>(Object, Method));
    1395           2 :   }
    1396          24 : 
    1397             :   /// Return type for non-blocking call primitives.
    1398             :   template <typename Func>
    1399           0 :   using NonBlockingCallResult = typename detail::ResultTraits<
    1400           0 :       typename Func::ReturnType>::ReturnFutureType;
    1401           1 : 
    1402             :   /// Call Func on Channel C. Does not block, does not call send. Returns a pair
    1403           1 :   /// of a future result and the sequence number assigned to the result.
    1404             :   ///
    1405             :   /// This utility function is primarily used for single-threaded mode support,
    1406             :   /// where the sequence number can be used to wait for the corresponding
    1407           0 :   /// result. In multi-threaded mode the appendCallNB method, which does not
    1408           2 :   /// return the sequence numeber, should be preferred.
    1409           0 :   template <typename Func, typename... ArgTs>
    1410           0 :   Expected<NonBlockingCallResult<Func>> appendCallNB(const ArgTs &... Args) {
    1411           0 :     using RTraits = detail::ResultTraits<typename Func::ReturnType>;
    1412             :     using ErrorReturn = typename RTraits::ErrorReturnType;
    1413           0 :     using ErrorReturnPromise = typename RTraits::ReturnPromiseType;
    1414           2 : 
    1415             :     // FIXME: Stack allocate and move this into the handler once LLVM builds
    1416             :     //        with C++14.
    1417           0 :     auto Promise = std::make_shared<ErrorReturnPromise>();
    1418           0 :     auto FutureResult = Promise->get_future();
    1419           0 : 
    1420           0 :     if (auto Err = this->template appendCallAsync<Func>(
    1421             :             [Promise](ErrorReturn RetOrErr) {
    1422           0 :               Promise->set_value(std::move(RetOrErr));
    1423             :               return Error::success();
    1424           0 :             },
    1425           0 :             Args...)) {
    1426           0 :       RTraits::consumeAbandoned(FutureResult.get());
    1427             :       return std::move(Err);
    1428           0 :     }
    1429             :     return std::move(FutureResult);
    1430           0 :   }
    1431           0 : 
    1432           0 :   /// The same as appendCallNBWithSeq, except that it calls C.send() to
    1433             :   /// flush the channel after serializing the call.
    1434           0 :   template <typename Func, typename... ArgTs>
    1435             :   Expected<NonBlockingCallResult<Func>> callNB(const ArgTs &... Args) {
    1436           0 :     auto Result = appendCallNB<Func>(Args...);
    1437             :     if (!Result)
    1438             :       return Result;
    1439             :     if (auto Err = this->C.send()) {
    1440             :       this->abandonPendingResponses();
    1441             :       detail::ResultTraits<typename Func::ReturnType>::consumeAbandoned(
    1442             :           std::move(Result->get()));
    1443           0 :       return std::move(Err);
    1444             :     }
    1445             :     return Result;
    1446           0 :   }
    1447             : 
    1448             :   /// Call Func on Channel C. Blocks waiting for a result. Returns an Error
    1449             :   /// for void functions or an Expected<T> for functions returning a T.
    1450           2 :   ///
    1451             :   /// This function is for use in threaded code where another thread is
    1452           4 :   /// handling responses and incoming calls.
    1453             :   template <typename Func, typename... ArgTs,
    1454             :             typename AltRetT = typename Func::ReturnType>
    1455             :   typename detail::ResultTraits<AltRetT>::ErrorReturnType
    1456             :   callB(const ArgTs &... Args) {
    1457           3 :     if (auto FutureResOrErr = callNB<Func>(Args...))
    1458             :       return FutureResOrErr->get();
    1459           1 :     else
    1460             :       return FutureResOrErr.takeError();
    1461           2 :   }
    1462             : 
    1463             :   /// Handle incoming RPC calls.
    1464             :   Error handlerLoop() {
    1465             :     while (true)
    1466           1 :       if (auto Err = this->handleOne())
    1467             :         return Err;
    1468           1 :     return Error::success();
    1469             :   }
    1470           2 : };
    1471          16 : 
    1472          48 : template <typename ChannelT, typename FunctionIdT = uint32_t,
    1473             :           typename SequenceNumberT = uint32_t>
    1474             : class SingleThreadedRPCEndpoint
    1475          18 :     : public detail::RPCEndpointBase<
    1476          16 :           SingleThreadedRPCEndpoint<ChannelT, FunctionIdT, SequenceNumberT>,
    1477             :           ChannelT, FunctionIdT, SequenceNumberT> {
    1478             : private:
    1479          16 :   using BaseClass =
    1480          16 :       detail::RPCEndpointBase<
    1481          16 :         SingleThreadedRPCEndpoint<ChannelT, FunctionIdT, SequenceNumberT>,
    1482             :         ChannelT, FunctionIdT, SequenceNumberT>;
    1483          16 : 
    1484             : public:
    1485           0 :   SingleThreadedRPCEndpoint(ChannelT &C, bool LazyAutoNegotiation)
    1486           0 :       : BaseClass(C, LazyAutoNegotiation) {}
    1487           0 : 
    1488             :   template <typename Func, typename HandlerT>
    1489           0 :   void addHandler(HandlerT Handler) {
    1490             :     return this->template addHandlerImpl<Func>(std::move(Handler));
    1491           0 :   }
    1492           0 : 
    1493           0 :   template <typename Func, typename ClassT, typename RetT, typename... ArgTs>
    1494             :   void addHandler(ClassT &Object, RetT (ClassT::*Method)(ArgTs...)) {
    1495           0 :     addHandler<Func>(
    1496             :         detail::MemberFnWrapper<ClassT, RetT, ArgTs...>(Object, Method));
    1497          75 :   }
    1498          72 : 
    1499             :   template <typename Func, typename HandlerT>
    1500             :   void addAsyncHandler(HandlerT Handler) {
    1501          24 :     return this->template addAsyncHandlerImpl<Func>(std::move(Handler));
    1502          24 :   }
    1503             : 
    1504             :   /// Add a class-method as a handler.
    1505          24 :   template <typename Func, typename ClassT, typename RetT, typename... ArgTs>
    1506          75 :   void addAsyncHandler(ClassT &Object, RetT (ClassT::*Method)(ArgTs...)) {
    1507          75 :     addAsyncHandler<Func>(
    1508             :       detail::MemberFnWrapper<ClassT, RetT, ArgTs...>(Object, Method));
    1509          24 :   }
    1510             : 
    1511           0 :   template <typename Func, typename... ArgTs,
    1512             :             typename AltRetT = typename Func::ReturnType>
    1513           0 :   typename detail::ResultTraits<AltRetT>::ErrorReturnType
    1514             :   callB(const ArgTs &... Args) {
    1515           0 :     bool ReceivedResponse = false;
    1516             :     using ResultType = typename detail::ResultTraits<AltRetT>::ErrorReturnType;
    1517           0 :     auto Result = detail::ResultTraits<AltRetT>::createBlankErrorReturnValue();
    1518          51 : 
    1519           0 :     // We have to 'Check' result (which we know is in a success state at this
    1520             :     // point) so that it can be overwritten in the async handler.
    1521          51 :     (void)!!Result;
    1522             : 
    1523         526 :     if (auto Err = this->template appendCallAsync<Func>(
    1524             :             [&](ResultType R) {
    1525           0 :               Result = std::move(R);
    1526          51 :               ReceivedResponse = true;
    1527           0 :               return Error::success();
    1528             :             },
    1529           0 :             Args...)) {
    1530             :       detail::ResultTraits<typename Func::ReturnType>::consumeAbandoned(
    1531           0 :           std::move(Result));
    1532         628 :       return std::move(Err);
    1533         526 :     }
    1534             : 
    1535           0 :     while (!ReceivedResponse) {
    1536             :       if (auto Err = this->handleOne()) {
    1537           0 :         detail::ResultTraits<typename Func::ReturnType>::consumeAbandoned(
    1538          89 :             std::move(Result));
    1539           0 :         return std::move(Err);
    1540           0 :       }
    1541           0 :     }
    1542             : 
    1543           0 :     return Result;
    1544         526 :   }
    1545          43 : };
    1546             : 
    1547         526 : /// Asynchronous dispatch for a function on an RPC endpoint.
    1548             : template <typename RPCClass, typename Func>
    1549           0 : class RPCAsyncDispatch {
    1550             : public:
    1551           0 :   RPCAsyncDispatch(RPCClass &Endpoint) : Endpoint(Endpoint) {}
    1552         528 : 
    1553           0 :   template <typename HandlerT, typename... ArgTs>
    1554             :   Error operator()(HandlerT Handler, const ArgTs &... Args) const {
    1555           0 :     return Endpoint.template appendCallAsync<Func>(std::move(Handler), Args...);
    1556             :   }
    1557             : 
    1558        1052 : private:
    1559          24 :   RPCClass &Endpoint;
    1560          72 : };
    1561           2 : 
    1562           2 : /// Construct an asynchronous dispatcher from an RPC endpoint and a Func.
    1563          24 : template <typename Func, typename RPCEndpointT>
    1564         843 : RPCAsyncDispatch<RPCEndpointT, Func> rpcAsyncDispatch(RPCEndpointT &Endpoint) {
    1565             :   return RPCAsyncDispatch<RPCEndpointT, Func>(Endpoint);
    1566           0 : }
    1567          24 : 
    1568          24 : /// Allows a set of asynchrounous calls to be dispatched, and then
    1569          24 : ///        waited on as a group.
    1570             : class ParallelCallGroup {
    1571         502 : public:
    1572             : 
    1573           2 :   ParallelCallGroup() = default;
    1574             :   ParallelCallGroup(const ParallelCallGroup &) = delete;
    1575             :   ParallelCallGroup &operator=(const ParallelCallGroup &) = delete;
    1576           2 : 
    1577             :   /// Make as asynchronous call.
    1578         201 :   template <typename AsyncDispatcher, typename HandlerT, typename... ArgTs>
    1579             :   Error call(const AsyncDispatcher &AsyncDispatch, HandlerT Handler,
    1580             :              const ArgTs &... Args) {
    1581           2 :     // Increment the count of outstanding calls. This has to happen before
    1582             :     // we invoke the call, as the handler may (depending on scheduling)
    1583             :     // be run immediately on another thread, and we don't want the decrement
    1584             :     // in the wrapped handler below to run before the increment.
    1585           0 :     {
    1586             :       std::unique_lock<std::mutex> Lock(M);
    1587         205 :       ++NumOutstandingCalls;
    1588         201 :     }
    1589             : 
    1590             :     // Wrap the user handler in a lambda that will decrement the
    1591             :     // outstanding calls count, then poke the condition variable.
    1592           0 :     using ArgType = typename detail::ResponseHandlerArg<
    1593           4 :         typename detail::HandlerTraits<HandlerT>::Type>::ArgType;
    1594           0 :     // FIXME: Move handler into wrapped handler once we have C++14.
    1595           0 :     auto WrappedHandler = [this, Handler](ArgType Arg) {
    1596             :       auto Err = Handler(std::move(Arg));
    1597          33 :       std::unique_lock<std::mutex> Lock(M);
    1598             :       --NumOutstandingCalls;
    1599         201 :       CV.notify_all();
    1600           2 :       return Err;
    1601           0 :     };
    1602         201 : 
    1603             :     return AsyncDispatch(std::move(WrappedHandler), Args...);
    1604           0 :   }
    1605             : 
    1606           0 :   /// Blocks until all calls have been completed and their return value
    1607         201 :   ///        handlers run.
    1608           0 :   void wait() {
    1609           0 :     std::unique_lock<std::mutex> Lock(M);
    1610           0 :     while (NumOutstandingCalls > 0)
    1611           0 :       CV.wait(Lock);
    1612           0 :   }
    1613         402 : 
    1614           0 : private:
    1615             :   std::mutex M;
    1616           0 :   std::condition_variable CV;
    1617           0 :   uint32_t NumOutstandingCalls = 0;
    1618          36 : };
    1619         438 : 
    1620          36 : /// Convenience class for grouping RPC Functions into APIs that can be
    1621          36 : ///        negotiated as a block.
    1622             : ///
    1623             : template <typename... Funcs>
    1624             : class APICalls {
    1625             : public:
    1626         201 : 
    1627             :   /// Test whether this API contains Function F.
    1628           0 :   template <typename F>
    1629             :   class Contains {
    1630             :   public:
    1631           0 :     static const bool value = false;
    1632             :   };
    1633           0 : 
    1634             :   /// Negotiate all functions in this API.
    1635             :   template <typename RPCEndpoint>
    1636           0 :   static Error negotiate(RPCEndpoint &R) {
    1637             :     return Error::success();
    1638             :   }
    1639             : };
    1640           0 : 
    1641             : template <typename Func, typename... Funcs>
    1642           0 : class APICalls<Func, Funcs...> {
    1643           0 : public:
    1644             : 
    1645             :   template <typename F>
    1646             :   class Contains {
    1647             :   public:
    1648           0 :     static const bool value = std::is_same<F, Func>::value |
    1649           0 :                               APICalls<Funcs...>::template Contains<F>::value;
    1650           0 :   };
    1651             : 
    1652             :   template <typename RPCEndpoint>
    1653             :   static Error negotiate(RPCEndpoint &R) {
    1654           0 :     if (auto Err = R.template negotiateFunction<Func>())
    1655           0 :       return Err;
    1656             :     return APICalls<Funcs...>::negotiate(R);
    1657           0 :   }
    1658             : 
    1659             : };
    1660             : 
    1661           0 : template <typename... InnerFuncs, typename... Funcs>
    1662          24 : class APICalls<APICalls<InnerFuncs...>, Funcs...> {
    1663             : public:
    1664           0 : 
    1665             :   template <typename F>
    1666             :   class Contains {
    1667             :   public:
    1668           0 :     static const bool value =
    1669           0 :       APICalls<InnerFuncs...>::template Contains<F>::value |
    1670             :       APICalls<Funcs...>::template Contains<F>::value;
    1671          24 :   };
    1672          24 : 
    1673             :   template <typename RPCEndpoint>
    1674           0 :   static Error negotiate(RPCEndpoint &R) {
    1675           0 :     if (auto Err = APICalls<InnerFuncs...>::negotiate(R))
    1676           0 :       return Err;
    1677             :     return APICalls<Funcs...>::negotiate(R);
    1678             :   }
    1679             : 
    1680             : };
    1681           0 : 
    1682             : } // end namespace rpc
    1683          24 : } // end namespace orc
    1684             : } // end namespace llvm
    1685             : 
    1686          24 : #endif

Generated by: LCOV version 1.13