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