Home | History | Annotate | Download | only in Orc
      1 //===----- RPCUTils.h - Basic tilities 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 // Basic utilities for building RPC APIs.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #ifndef LLVM_EXECUTIONENGINE_ORC_RPCUTILS_H
     15 #define LLVM_EXECUTIONENGINE_ORC_RPCUTILS_H
     16 
     17 #include <map>
     18 #include <vector>
     19 
     20 #include "llvm/ADT/Optional.h"
     21 #include "llvm/ADT/STLExtras.h"
     22 #include "llvm/ExecutionEngine/Orc/OrcError.h"
     23 
     24 #ifdef _MSC_VER
     25 // concrt.h depends on eh.h for __uncaught_exception declaration
     26 // even if we disable exceptions.
     27 #include <eh.h>
     28 
     29 // Disable warnings from ppltasks.h transitively included by <future>.
     30 #pragma warning(push)
     31 #pragma warning(disable : 4530)
     32 #pragma warning(disable : 4062)
     33 #endif
     34 
     35 #include <future>
     36 
     37 #ifdef _MSC_VER
     38 #pragma warning(pop)
     39 #endif
     40 
     41 namespace llvm {
     42 namespace orc {
     43 namespace remote {
     44 
     45 /// Describes reserved RPC Function Ids.
     46 ///
     47 /// The default implementation will serve for integer and enum function id
     48 /// types. If you want to use a custom type as your FunctionId you can
     49 /// specialize this class and provide unique values for InvalidId,
     50 /// ResponseId and FirstValidId.
     51 
     52 template <typename T> class RPCFunctionIdTraits {
     53 public:
     54   static const T InvalidId = static_cast<T>(0);
     55   static const T ResponseId = static_cast<T>(1);
     56   static const T FirstValidId = static_cast<T>(2);
     57 };
     58 
     59 // Base class containing utilities that require partial specialization.
     60 // These cannot be included in RPC, as template class members cannot be
     61 // partially specialized.
     62 class RPCBase {
     63 protected:
     64   // RPC Function description type.
     65   //
     66   // This class provides the information and operations needed to support the
     67   // RPC primitive operations (call, expect, etc) for a given function. It
     68   // is specialized for void and non-void functions to deal with the differences
     69   // betwen the two. Both specializations have the same interface:
     70   //
     71   // Id - The function's unique identifier.
     72   // OptionalReturn - The return type for asyncronous calls.
     73   // ErrorReturn - The return type for synchronous calls.
     74   // optionalToErrorReturn - Conversion from a valid OptionalReturn to an
     75   //                         ErrorReturn.
     76   // readResult - Deserialize a result from a channel.
     77   // abandon - Abandon a promised (asynchronous) result.
     78   // respond - Retun a result on the channel.
     79   template <typename FunctionIdT, FunctionIdT FuncId, typename FnT>
     80   class FunctionHelper {};
     81 
     82   // RPC Function description specialization for non-void functions.
     83   template <typename FunctionIdT, FunctionIdT FuncId, typename RetT,
     84             typename... ArgTs>
     85   class FunctionHelper<FunctionIdT, FuncId, RetT(ArgTs...)> {
     86   public:
     87     static_assert(FuncId != RPCFunctionIdTraits<FunctionIdT>::InvalidId &&
     88                       FuncId != RPCFunctionIdTraits<FunctionIdT>::ResponseId,
     89                   "Cannot define custom function with InvalidId or ResponseId. "
     90                   "Please use RPCFunctionTraits<FunctionIdT>::FirstValidId.");
     91 
     92     static const FunctionIdT Id = FuncId;
     93 
     94     typedef Optional<RetT> OptionalReturn;
     95 
     96     typedef Expected<RetT> ErrorReturn;
     97 
     98     static ErrorReturn optionalToErrorReturn(OptionalReturn &&V) {
     99       assert(V && "Return value not available");
    100       return std::move(*V);
    101     }
    102 
    103     template <typename ChannelT>
    104     static Error readResult(ChannelT &C, std::promise<OptionalReturn> &P) {
    105       RetT Val;
    106       auto Err = deserialize(C, Val);
    107       auto Err2 = endReceiveMessage(C);
    108       Err = joinErrors(std::move(Err), std::move(Err2));
    109 
    110       if (Err) {
    111         P.set_value(OptionalReturn());
    112         return Err;
    113       }
    114       P.set_value(std::move(Val));
    115       return Error::success();
    116     }
    117 
    118     static void abandon(std::promise<OptionalReturn> &P) {
    119       P.set_value(OptionalReturn());
    120     }
    121 
    122     template <typename ChannelT, typename SequenceNumberT>
    123     static Error respond(ChannelT &C, SequenceNumberT SeqNo,
    124                          ErrorReturn &Result) {
    125       FunctionIdT ResponseId = RPCFunctionIdTraits<FunctionIdT>::ResponseId;
    126 
    127       // If the handler returned an error then bail out with that.
    128       if (!Result)
    129         return Result.takeError();
    130 
    131       // Otherwise open a new message on the channel and send the result.
    132       if (auto Err = startSendMessage(C))
    133         return Err;
    134       if (auto Err = serializeSeq(C, ResponseId, SeqNo, *Result))
    135         return Err;
    136       return endSendMessage(C);
    137     }
    138   };
    139 
    140   // RPC Function description specialization for void functions.
    141   template <typename FunctionIdT, FunctionIdT FuncId, typename... ArgTs>
    142   class FunctionHelper<FunctionIdT, FuncId, void(ArgTs...)> {
    143   public:
    144     static_assert(FuncId != RPCFunctionIdTraits<FunctionIdT>::InvalidId &&
    145                       FuncId != RPCFunctionIdTraits<FunctionIdT>::ResponseId,
    146                   "Cannot define custom function with InvalidId or ResponseId. "
    147                   "Please use RPCFunctionTraits<FunctionIdT>::FirstValidId.");
    148 
    149     static const FunctionIdT Id = FuncId;
    150 
    151     typedef bool OptionalReturn;
    152     typedef Error ErrorReturn;
    153 
    154     static ErrorReturn optionalToErrorReturn(OptionalReturn &&V) {
    155       assert(V && "Return value not available");
    156       return Error::success();
    157     }
    158 
    159     template <typename ChannelT>
    160     static Error readResult(ChannelT &C, std::promise<OptionalReturn> &P) {
    161       // Void functions don't have anything to deserialize, so we're good.
    162       P.set_value(true);
    163       return endReceiveMessage(C);
    164     }
    165 
    166     static void abandon(std::promise<OptionalReturn> &P) { P.set_value(false); }
    167 
    168     template <typename ChannelT, typename SequenceNumberT>
    169     static Error respond(ChannelT &C, SequenceNumberT SeqNo,
    170                          ErrorReturn &Result) {
    171       const FunctionIdT ResponseId =
    172           RPCFunctionIdTraits<FunctionIdT>::ResponseId;
    173 
    174       // If the handler returned an error then bail out with that.
    175       if (Result)
    176         return std::move(Result);
    177 
    178       // Otherwise open a new message on the channel and send the result.
    179       if (auto Err = startSendMessage(C))
    180         return Err;
    181       if (auto Err = serializeSeq(C, ResponseId, SeqNo))
    182         return Err;
    183       return endSendMessage(C);
    184     }
    185   };
    186 
    187   // Helper for the call primitive.
    188   template <typename ChannelT, typename SequenceNumberT, typename Func>
    189   class CallHelper;
    190 
    191   template <typename ChannelT, typename SequenceNumberT, typename FunctionIdT,
    192             FunctionIdT FuncId, typename RetT, typename... ArgTs>
    193   class CallHelper<ChannelT, SequenceNumberT,
    194                    FunctionHelper<FunctionIdT, FuncId, RetT(ArgTs...)>> {
    195   public:
    196     static Error call(ChannelT &C, SequenceNumberT SeqNo,
    197                       const ArgTs &... Args) {
    198       if (auto Err = startSendMessage(C))
    199         return Err;
    200       if (auto Err = serializeSeq(C, FuncId, SeqNo, Args...))
    201         return Err;
    202       return endSendMessage(C);
    203     }
    204   };
    205 
    206   // Helper for handle primitive.
    207   template <typename ChannelT, typename SequenceNumberT, typename Func>
    208   class HandlerHelper;
    209 
    210   template <typename ChannelT, typename SequenceNumberT, typename FunctionIdT,
    211             FunctionIdT FuncId, typename RetT, typename... ArgTs>
    212   class HandlerHelper<ChannelT, SequenceNumberT,
    213                       FunctionHelper<FunctionIdT, FuncId, RetT(ArgTs...)>> {
    214   public:
    215     template <typename HandlerT>
    216     static Error handle(ChannelT &C, HandlerT Handler) {
    217       return readAndHandle(C, Handler, llvm::index_sequence_for<ArgTs...>());
    218     }
    219 
    220   private:
    221     typedef FunctionHelper<FunctionIdT, FuncId, RetT(ArgTs...)> Func;
    222 
    223     template <typename HandlerT, size_t... Is>
    224     static Error readAndHandle(ChannelT &C, HandlerT Handler,
    225                                llvm::index_sequence<Is...> _) {
    226       std::tuple<ArgTs...> RPCArgs;
    227       SequenceNumberT SeqNo;
    228       // GCC 4.7 and 4.8 incorrectly issue a -Wunused-but-set-variable warning
    229       // for RPCArgs. Void cast RPCArgs to work around this for now.
    230       // FIXME: Remove this workaround once we can assume a working GCC version.
    231       (void)RPCArgs;
    232       if (auto Err = deserializeSeq(C, SeqNo, std::get<Is>(RPCArgs)...))
    233         return Err;
    234 
    235       // We've deserialized the arguments, so unlock the channel for reading
    236       // before we call the handler. This allows recursive RPC calls.
    237       if (auto Err = endReceiveMessage(C))
    238         return Err;
    239 
    240       // Run the handler and get the result.
    241       auto Result = Handler(std::get<Is>(RPCArgs)...);
    242 
    243       // Return the result to the client.
    244       return Func::template respond<ChannelT, SequenceNumberT>(C, SeqNo,
    245                                                                Result);
    246     }
    247   };
    248 
    249   // Helper for wrapping member functions up as functors.
    250   template <typename ClassT, typename RetT, typename... ArgTs>
    251   class MemberFnWrapper {
    252   public:
    253     typedef RetT (ClassT::*MethodT)(ArgTs...);
    254     MemberFnWrapper(ClassT &Instance, MethodT Method)
    255         : Instance(Instance), Method(Method) {}
    256     RetT operator()(ArgTs &... Args) { return (Instance.*Method)(Args...); }
    257 
    258   private:
    259     ClassT &Instance;
    260     MethodT Method;
    261   };
    262 
    263   // Helper that provides a Functor for deserializing arguments.
    264   template <typename... ArgTs> class ReadArgs {
    265   public:
    266     Error operator()() { return Error::success(); }
    267   };
    268 
    269   template <typename ArgT, typename... ArgTs>
    270   class ReadArgs<ArgT, ArgTs...> : public ReadArgs<ArgTs...> {
    271   public:
    272     ReadArgs(ArgT &Arg, ArgTs &... Args)
    273         : ReadArgs<ArgTs...>(Args...), Arg(Arg) {}
    274 
    275     Error operator()(ArgT &ArgVal, ArgTs &... ArgVals) {
    276       this->Arg = std::move(ArgVal);
    277       return ReadArgs<ArgTs...>::operator()(ArgVals...);
    278     }
    279 
    280   private:
    281     ArgT &Arg;
    282   };
    283 };
    284 
    285 /// Contains primitive utilities for defining, calling and handling calls to
    286 /// remote procedures. ChannelT is a bidirectional stream conforming to the
    287 /// RPCChannel interface (see RPCChannel.h), and FunctionIdT is a procedure
    288 /// identifier type that must be serializable on ChannelT.
    289 ///
    290 /// These utilities support the construction of very primitive RPC utilities.
    291 /// Their intent is to ensure correct serialization and deserialization of
    292 /// procedure arguments, and to keep the client and server's view of the API in
    293 /// sync.
    294 ///
    295 /// These utilities do not support return values. These can be handled by
    296 /// declaring a corresponding '.*Response' procedure and expecting it after a
    297 /// call). They also do not support versioning: the client and server *must* be
    298 /// compiled with the same procedure definitions.
    299 ///
    300 ///
    301 ///
    302 /// Overview (see comments individual types/methods for details):
    303 ///
    304 /// Function<Id, Args...> :
    305 ///
    306 ///   associates a unique serializable id with an argument list.
    307 ///
    308 ///
    309 /// call<Func>(Channel, Args...) :
    310 ///
    311 ///   Calls the remote procedure 'Func' by serializing Func's id followed by its
    312 /// arguments and sending the resulting bytes to 'Channel'.
    313 ///
    314 ///
    315 /// handle<Func>(Channel, <functor matching Error(Args...)> :
    316 ///
    317 ///   Handles a call to 'Func' by deserializing its arguments and calling the
    318 /// given functor. This assumes that the id for 'Func' has already been
    319 /// deserialized.
    320 ///
    321 /// expect<Func>(Channel, <functor matching Error(Args...)> :
    322 ///
    323 ///   The same as 'handle', except that the procedure id should not have been
    324 /// read yet. Expect will deserialize the id and assert that it matches Func's
    325 /// id. If it does not, and unexpected RPC call error is returned.
    326 template <typename ChannelT, typename FunctionIdT = uint32_t,
    327           typename SequenceNumberT = uint16_t>
    328 class RPC : public RPCBase {
    329 public:
    330   /// RPC default constructor.
    331   RPC() = default;
    332 
    333   /// RPC instances cannot be copied.
    334   RPC(const RPC &) = delete;
    335 
    336   /// RPC instances cannot be copied.
    337   RPC &operator=(const RPC &) = delete;
    338 
    339   /// RPC move constructor.
    340   // FIXME: Remove once MSVC can synthesize move ops.
    341   RPC(RPC &&Other)
    342       : SequenceNumberMgr(std::move(Other.SequenceNumberMgr)),
    343         OutstandingResults(std::move(Other.OutstandingResults)) {}
    344 
    345   /// RPC move assignment.
    346   // FIXME: Remove once MSVC can synthesize move ops.
    347   RPC &operator=(RPC &&Other) {
    348     SequenceNumberMgr = std::move(Other.SequenceNumberMgr);
    349     OutstandingResults = std::move(Other.OutstandingResults);
    350     return *this;
    351   }
    352 
    353   /// Utility class for defining/referring to RPC procedures.
    354   ///
    355   /// Typedefs of this utility are used when calling/handling remote procedures.
    356   ///
    357   /// FuncId should be a unique value of FunctionIdT (i.e. not used with any
    358   /// other Function typedef in the RPC API being defined.
    359   ///
    360   /// the template argument Ts... gives the argument list for the remote
    361   /// procedure.
    362   ///
    363   /// E.g.
    364   ///
    365   ///   typedef Function<0, bool> Func1;
    366   ///   typedef Function<1, std::string, std::vector<int>> Func2;
    367   ///
    368   ///   if (auto Err = call<Func1>(Channel, true))
    369   ///     /* handle Err */;
    370   ///
    371   ///   if (auto Err = expect<Func2>(Channel,
    372   ///         [](std::string &S, std::vector<int> &V) {
    373   ///           // Stuff.
    374   ///           return Error::success();
    375   ///         })
    376   ///     /* handle Err */;
    377   ///
    378   template <FunctionIdT FuncId, typename FnT>
    379   using Function = FunctionHelper<FunctionIdT, FuncId, FnT>;
    380 
    381   /// Return type for asynchronous call primitives.
    382   template <typename Func>
    383   using AsyncCallResult = std::future<typename Func::OptionalReturn>;
    384 
    385   /// Return type for asynchronous call-with-seq primitives.
    386   template <typename Func>
    387   using AsyncCallWithSeqResult =
    388       std::pair<std::future<typename Func::OptionalReturn>, SequenceNumberT>;
    389 
    390   /// Serialize Args... to channel C, but do not call C.send().
    391   ///
    392   /// Returns an error (on serialization failure) or a pair of:
    393   /// (1) A future Optional<T> (or future<bool> for void functions), and
    394   /// (2) A sequence number.
    395   ///
    396   /// This utility function is primarily used for single-threaded mode support,
    397   /// where the sequence number can be used to wait for the corresponding
    398   /// result. In multi-threaded mode the appendCallAsync method, which does not
    399   /// return the sequence numeber, should be preferred.
    400   template <typename Func, typename... ArgTs>
    401   Expected<AsyncCallWithSeqResult<Func>>
    402   appendCallAsyncWithSeq(ChannelT &C, const ArgTs &... Args) {
    403     auto SeqNo = SequenceNumberMgr.getSequenceNumber();
    404     std::promise<typename Func::OptionalReturn> Promise;
    405     auto Result = Promise.get_future();
    406     OutstandingResults[SeqNo] =
    407         createOutstandingResult<Func>(std::move(Promise));
    408 
    409     if (auto Err = CallHelper<ChannelT, SequenceNumberT, Func>::call(C, SeqNo,
    410                                                                      Args...)) {
    411       abandonOutstandingResults();
    412       return std::move(Err);
    413     } else
    414       return AsyncCallWithSeqResult<Func>(std::move(Result), SeqNo);
    415   }
    416 
    417   /// The same as appendCallAsyncWithSeq, except that it calls C.send() to
    418   /// flush the channel after serializing the call.
    419   template <typename Func, typename... ArgTs>
    420   Expected<AsyncCallWithSeqResult<Func>>
    421   callAsyncWithSeq(ChannelT &C, const ArgTs &... Args) {
    422     auto Result = appendCallAsyncWithSeq<Func>(C, Args...);
    423     if (!Result)
    424       return Result;
    425     if (auto Err = C.send()) {
    426       abandonOutstandingResults();
    427       return std::move(Err);
    428     }
    429     return Result;
    430   }
    431 
    432   /// Serialize Args... to channel C, but do not call send.
    433   /// Returns an error if serialization fails, otherwise returns a
    434   /// std::future<Optional<T>> (or a future<bool> for void functions).
    435   template <typename Func, typename... ArgTs>
    436   Expected<AsyncCallResult<Func>> appendCallAsync(ChannelT &C,
    437                                                   const ArgTs &... Args) {
    438     auto ResAndSeqOrErr = appendCallAsyncWithSeq<Func>(C, Args...);
    439     if (ResAndSeqOrErr)
    440       return std::move(ResAndSeqOrErr->first);
    441     return ResAndSeqOrErr.getError();
    442   }
    443 
    444   /// The same as appendCallAsync, except that it calls C.send to flush the
    445   /// channel after serializing the call.
    446   template <typename Func, typename... ArgTs>
    447   Expected<AsyncCallResult<Func>> callAsync(ChannelT &C,
    448                                             const ArgTs &... Args) {
    449     auto ResAndSeqOrErr = callAsyncWithSeq<Func>(C, Args...);
    450     if (ResAndSeqOrErr)
    451       return std::move(ResAndSeqOrErr->first);
    452     return ResAndSeqOrErr.getError();
    453   }
    454 
    455   /// This can be used in single-threaded mode.
    456   template <typename Func, typename HandleFtor, typename... ArgTs>
    457   typename Func::ErrorReturn
    458   callSTHandling(ChannelT &C, HandleFtor &HandleOther, const ArgTs &... Args) {
    459     if (auto ResultAndSeqNoOrErr = callAsyncWithSeq<Func>(C, Args...)) {
    460       auto &ResultAndSeqNo = *ResultAndSeqNoOrErr;
    461       if (auto Err = waitForResult(C, ResultAndSeqNo.second, HandleOther))
    462         return std::move(Err);
    463       return Func::optionalToErrorReturn(ResultAndSeqNo.first.get());
    464     } else
    465       return ResultAndSeqNoOrErr.takeError();
    466   }
    467 
    468   // This can be used in single-threaded mode.
    469   template <typename Func, typename... ArgTs>
    470   typename Func::ErrorReturn callST(ChannelT &C, const ArgTs &... Args) {
    471     return callSTHandling<Func>(C, handleNone, Args...);
    472   }
    473 
    474   /// Start receiving a new function call.
    475   ///
    476   /// Calls startReceiveMessage on the channel, then deserializes a FunctionId
    477   /// into Id.
    478   Error startReceivingFunction(ChannelT &C, FunctionIdT &Id) {
    479     if (auto Err = startReceiveMessage(C))
    480       return Err;
    481 
    482     return deserialize(C, Id);
    483   }
    484 
    485   /// Deserialize args for Func from C and call Handler. The signature of
    486   /// handler must conform to 'Error(Args...)' where Args... matches
    487   /// the arguments used in the Func typedef.
    488   template <typename Func, typename HandlerT>
    489   static Error handle(ChannelT &C, HandlerT Handler) {
    490     return HandlerHelper<ChannelT, SequenceNumberT, Func>::handle(C, Handler);
    491   }
    492 
    493   /// Helper version of 'handle' for calling member functions.
    494   template <typename Func, typename ClassT, typename RetT, typename... ArgTs>
    495   static Error handle(ChannelT &C, ClassT &Instance,
    496                       RetT (ClassT::*HandlerMethod)(ArgTs...)) {
    497     return handle<Func>(
    498         C, MemberFnWrapper<ClassT, RetT, ArgTs...>(Instance, HandlerMethod));
    499   }
    500 
    501   /// Deserialize a FunctionIdT from C and verify it matches the id for Func.
    502   /// If the id does match, deserialize the arguments and call the handler
    503   /// (similarly to handle).
    504   /// If the id does not match, return an unexpect RPC call error and do not
    505   /// deserialize any further bytes.
    506   template <typename Func, typename HandlerT>
    507   Error expect(ChannelT &C, HandlerT Handler) {
    508     FunctionIdT FuncId;
    509     if (auto Err = startReceivingFunction(C, FuncId))
    510       return std::move(Err);
    511     if (FuncId != Func::Id)
    512       return orcError(OrcErrorCode::UnexpectedRPCCall);
    513     return handle<Func>(C, Handler);
    514   }
    515 
    516   /// Helper version of expect for calling member functions.
    517   template <typename Func, typename ClassT, typename... ArgTs>
    518   static Error expect(ChannelT &C, ClassT &Instance,
    519                       Error (ClassT::*HandlerMethod)(ArgTs...)) {
    520     return expect<Func>(
    521         C, MemberFnWrapper<ClassT, ArgTs...>(Instance, HandlerMethod));
    522   }
    523 
    524   /// Helper for handling setter procedures - this method returns a functor that
    525   /// sets the variables referred to by Args... to values deserialized from the
    526   /// channel.
    527   /// E.g.
    528   ///
    529   ///   typedef Function<0, bool, int> Func1;
    530   ///
    531   ///   ...
    532   ///   bool B;
    533   ///   int I;
    534   ///   if (auto Err = expect<Func1>(Channel, readArgs(B, I)))
    535   ///     /* Handle Args */ ;
    536   ///
    537   template <typename... ArgTs>
    538   static ReadArgs<ArgTs...> readArgs(ArgTs &... Args) {
    539     return ReadArgs<ArgTs...>(Args...);
    540   }
    541 
    542   /// Read a response from Channel.
    543   /// This should be called from the receive loop to retrieve results.
    544   Error handleResponse(ChannelT &C, SequenceNumberT *SeqNoRet = nullptr) {
    545     SequenceNumberT SeqNo;
    546     if (auto Err = deserialize(C, SeqNo)) {
    547       abandonOutstandingResults();
    548       return Err;
    549     }
    550 
    551     if (SeqNoRet)
    552       *SeqNoRet = SeqNo;
    553 
    554     auto I = OutstandingResults.find(SeqNo);
    555     if (I == OutstandingResults.end()) {
    556       abandonOutstandingResults();
    557       return orcError(OrcErrorCode::UnexpectedRPCResponse);
    558     }
    559 
    560     if (auto Err = I->second->readResult(C)) {
    561       abandonOutstandingResults();
    562       // FIXME: Release sequence numbers?
    563       return Err;
    564     }
    565 
    566     OutstandingResults.erase(I);
    567     SequenceNumberMgr.releaseSequenceNumber(SeqNo);
    568 
    569     return Error::success();
    570   }
    571 
    572   // Loop waiting for a result with the given sequence number.
    573   // This can be used as a receive loop if the user doesn't have a default.
    574   template <typename HandleOtherFtor>
    575   Error waitForResult(ChannelT &C, SequenceNumberT TgtSeqNo,
    576                       HandleOtherFtor &HandleOther = handleNone) {
    577     bool GotTgtResult = false;
    578 
    579     while (!GotTgtResult) {
    580       FunctionIdT Id = RPCFunctionIdTraits<FunctionIdT>::InvalidId;
    581       if (auto Err = startReceivingFunction(C, Id))
    582         return Err;
    583       if (Id == RPCFunctionIdTraits<FunctionIdT>::ResponseId) {
    584         SequenceNumberT SeqNo;
    585         if (auto Err = handleResponse(C, &SeqNo))
    586           return Err;
    587         GotTgtResult = (SeqNo == TgtSeqNo);
    588       } else if (auto Err = HandleOther(C, Id))
    589         return Err;
    590     }
    591 
    592     return Error::success();
    593   }
    594 
    595   // Default handler for 'other' (non-response) functions when waiting for a
    596   // result from the channel.
    597   static Error handleNone(ChannelT &, FunctionIdT) {
    598     return orcError(OrcErrorCode::UnexpectedRPCCall);
    599   };
    600 
    601 private:
    602   // Manage sequence numbers.
    603   class SequenceNumberManager {
    604   public:
    605     SequenceNumberManager() = default;
    606 
    607     SequenceNumberManager(const SequenceNumberManager &) = delete;
    608     SequenceNumberManager &operator=(const SequenceNumberManager &) = delete;
    609 
    610     SequenceNumberManager(SequenceNumberManager &&Other)
    611         : NextSequenceNumber(std::move(Other.NextSequenceNumber)),
    612           FreeSequenceNumbers(std::move(Other.FreeSequenceNumbers)) {}
    613 
    614     SequenceNumberManager &operator=(SequenceNumberManager &&Other) {
    615       NextSequenceNumber = std::move(Other.NextSequenceNumber);
    616       FreeSequenceNumbers = std::move(Other.FreeSequenceNumbers);
    617     }
    618 
    619     void reset() {
    620       std::lock_guard<std::mutex> Lock(SeqNoLock);
    621       NextSequenceNumber = 0;
    622       FreeSequenceNumbers.clear();
    623     }
    624 
    625     SequenceNumberT getSequenceNumber() {
    626       std::lock_guard<std::mutex> Lock(SeqNoLock);
    627       if (FreeSequenceNumbers.empty())
    628         return NextSequenceNumber++;
    629       auto SequenceNumber = FreeSequenceNumbers.back();
    630       FreeSequenceNumbers.pop_back();
    631       return SequenceNumber;
    632     }
    633 
    634     void releaseSequenceNumber(SequenceNumberT SequenceNumber) {
    635       std::lock_guard<std::mutex> Lock(SeqNoLock);
    636       FreeSequenceNumbers.push_back(SequenceNumber);
    637     }
    638 
    639   private:
    640     std::mutex SeqNoLock;
    641     SequenceNumberT NextSequenceNumber = 0;
    642     std::vector<SequenceNumberT> FreeSequenceNumbers;
    643   };
    644 
    645   // Base class for results that haven't been returned from the other end of the
    646   // RPC connection yet.
    647   class OutstandingResult {
    648   public:
    649     virtual ~OutstandingResult() {}
    650     virtual Error readResult(ChannelT &C) = 0;
    651     virtual void abandon() = 0;
    652   };
    653 
    654   // Outstanding results for a specific function.
    655   template <typename Func>
    656   class OutstandingResultImpl : public OutstandingResult {
    657   private:
    658   public:
    659     OutstandingResultImpl(std::promise<typename Func::OptionalReturn> &&P)
    660         : P(std::move(P)) {}
    661 
    662     Error readResult(ChannelT &C) override { return Func::readResult(C, P); }
    663 
    664     void abandon() override { Func::abandon(P); }
    665 
    666   private:
    667     std::promise<typename Func::OptionalReturn> P;
    668   };
    669 
    670   // Create an outstanding result for the given function.
    671   template <typename Func>
    672   std::unique_ptr<OutstandingResult>
    673   createOutstandingResult(std::promise<typename Func::OptionalReturn> &&P) {
    674     return llvm::make_unique<OutstandingResultImpl<Func>>(std::move(P));
    675   }
    676 
    677   // Abandon all outstanding results.
    678   void abandonOutstandingResults() {
    679     for (auto &KV : OutstandingResults)
    680       KV.second->abandon();
    681     OutstandingResults.clear();
    682     SequenceNumberMgr.reset();
    683   }
    684 
    685   SequenceNumberManager SequenceNumberMgr;
    686   std::map<SequenceNumberT, std::unique_ptr<OutstandingResult>>
    687       OutstandingResults;
    688 };
    689 
    690 } // end namespace remote
    691 } // end namespace orc
    692 } // end namespace llvm
    693 
    694 #endif
    695