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