18 #ifndef LLVM_EXECUTIONENGINE_ORC_RPCUTILS_H 19 #define LLVM_EXECUTIONENGINE_ORC_RPCUTILS_H 58 template <
typename FnIdT,
typename SeqNoT>
60 :
public ErrorInfo<BadFunctionCall<FnIdT, SeqNoT>, RPCFatalError> {
65 : FnId(
std::move(FnId)), SeqNo(
std::move(SeqNo)) {}
72 OS <<
"Call to invalid RPC function id '" << FnId <<
"' with " 73 "sequence number " << SeqNo;
81 template <
typename FnIdT,
typename SeqNoT>
91 template <
typename SeqNoT>
93 :
public ErrorInfo<InvalidSequenceNumberForResponse<SeqNoT>, RPCFatalError> {
98 : SeqNo(
std::move(SeqNo)) {}
105 OS <<
"Response has unknown sequence number " << SeqNo;
111 template <
typename SeqNoT>
136 std::string Signature;
139 template <
typename DerivedFunc,
typename FnT>
class Function;
144 template <
typename DerivedFunc,
typename RetT,
typename... ArgTs>
155 std::lock_guard<std::mutex>
Lock(NameMutex);
164 static std::mutex NameMutex;
165 static std::string
Name;
168 template <
typename DerivedFunc,
typename RetT,
typename... ArgTs>
169 std::mutex
Function<DerivedFunc, RetT(ArgTs...)>::NameMutex;
171 template <
typename DerivedFunc,
typename RetT,
typename... ArgTs>
195 template <
typename T>
197 T, typename
std::enable_if<std::is_integral<T>::value>
::type> {
203 template <
typename Func>
T allocate() {
return NextId++; }
214 template <
typename RetT,
typename... ArgTs>
217 using Type = std::tuple<
typename std::decay<
218 typename std::remove_reference<ArgTs>::type>
::type...>;
296 template <
typename RetT>
301 template <
typename T>
304 static const bool value =
false;
310 static const bool value =
true;
313 template <
typename T>
316 static const bool value =
true;
321 template <
bool FuncSupportsErrorReturn>
330 template <
typename WireRetT,
typename HandlerRetT,
typename ChannelT,
331 typename FunctionIdT,
typename SequenceNumberT>
332 static Error
sendResult(ChannelT &
C,
const FunctionIdT &ResponseId,
333 SequenceNumberT SeqNo,
335 if (!ResultOrErr && ResultOrErr.template errorIsA<RPCFatalError>())
339 if (
auto Err = C.startSendMessage(ResponseId, SeqNo))
346 C, std::move(ResultOrErr)))
350 return C.endSendMessage();
353 template <
typename ChannelT,
typename FunctionIdT,
typename SequenceNumberT>
354 static Error
sendResult(ChannelT &
C,
const FunctionIdT &ResponseId,
355 SequenceNumberT SeqNo, Error Err) {
358 if (
auto Err2 = C.startSendMessage(ResponseId, SeqNo))
362 return C.endSendMessage();
372 template <
typename WireRetT,
typename HandlerRetT,
typename ChannelT,
373 typename FunctionIdT,
typename SequenceNumberT>
374 static Error
sendResult(ChannelT &
C,
const FunctionIdT &ResponseId,
375 SequenceNumberT SeqNo,
381 if (
auto Err = C.startSendMessage(ResponseId, SeqNo))
391 return C.endSendMessage();
394 template <
typename ChannelT,
typename FunctionIdT,
typename SequenceNumberT>
395 static Error
sendResult(ChannelT &
C,
const FunctionIdT &ResponseId,
396 SequenceNumberT SeqNo, Error Err) {
399 if (
auto Err2 = C.startSendMessage(ResponseId, SeqNo))
401 return C.endSendMessage();
409 template <
typename WireRetT,
typename HandlerRetT,
typename ChannelT,
410 typename FunctionIdT,
typename SequenceNumberT>
411 Error
respond(ChannelT &
C,
const FunctionIdT &ResponseId,
414 template sendResult<WireRetT>(
C, ResponseId, SeqNo, std::move(ResultOrErr));
419 template <
typename WireRetT,
typename ChannelT,
typename FunctionIdT,
420 typename SequenceNumberT>
421 Error
respond(ChannelT &
C,
const FunctionIdT &ResponseId, SequenceNumberT SeqNo,
424 sendResult(C, ResponseId, SeqNo, std::move(Err));
457 template <
typename ResultT,
typename... ArgTs>
464 template <
typename... ArgTs>
471 template <
typename... ArgTs>
478 template <
typename... ArgTs>
485 template <
typename ResponseHandlerT,
typename... ArgTs>
494 template <
typename HandlerT>
496 &std::remove_reference<HandlerT>::type::operator())> {
500 template <
typename RetT,
typename... ArgTs>
510 template <
typename HandlerT,
typename... TArgTs>
513 return unpackAndRunHelper(Handler, Args,
518 template <
typename HandlerT,
typename ResponderT,
typename... TArgTs>
520 std::tuple<TArgTs...> &
Args) {
521 return unpackAndRunAsyncHelper(Handler, Responder, Args,
526 template <
typename HandlerT>
527 static typename std::enable_if<
531 Handler(std::move(
Args)...);
535 template <
typename HandlerT,
typename... TArgTs>
536 static typename std::enable_if<
540 return Handler(std::move(
Args)...);
544 template <
typename ChannelT,
typename... CArgTs>
550 template <
typename ChannelT,
typename... CArgTs>
552 return deserializeArgsHelper(C, Args,
557 template <
typename ChannelT,
typename... CArgTs,
size_t... Indexes>
558 static Error deserializeArgsHelper(ChannelT &
C, std::tuple<CArgTs...> &
Args,
561 C, std::get<Indexes>(Args)...);
564 template <
typename HandlerT,
typename ArgTuple,
size_t... Indexes>
567 unpackAndRunHelper(HandlerT &Handler, ArgTuple &Args,
569 return run(Handler, std::move(std::get<Indexes>(Args))...);
573 template <
typename HandlerT,
typename ResponderT,
typename ArgTuple,
577 unpackAndRunAsyncHelper(HandlerT &Handler, ResponderT &Responder,
580 return run(Handler, Responder, std::move(std::get<Indexes>(Args))...);
585 template <
typename RetT,
typename... ArgTs>
590 template <
typename Class,
typename RetT,
typename... ArgTs>
596 template <
typename Class,
typename RetT,
typename... ArgTs>
609 template <
typename ArgT>
636 virtual Error handleResponse(ChannelT &
C) = 0;
639 virtual void abandon() = 0;
643 return make_error<ResponseAbandoned>();
648 template <
typename ChannelT,
typename FuncRetT,
typename HandlerT>
658 UnwrappedArgType Result;
661 UnwrappedArgType>::deserialize(C, Result))
663 if (
auto Err = C.endReceiveMessage())
665 return Handler(std::move(Result));
671 if (
auto Err = Handler(this->createAbandonedResponseError())) {
682 template <
typename ChannelT,
typename HandlerT>
692 if (
auto Err = C.endReceiveMessage())
700 if (
auto Err = Handler(this->createAbandonedResponseError())) {
710 template <
typename ChannelT,
typename FuncRetT,
typename HandlerT>
721 HandlerArgType Result((
typename HandlerArgType::value_type()));
725 HandlerArgType>::deserialize(C, Result))
727 if (
auto Err = C.endReceiveMessage())
729 return Handler(std::move(Result));
735 if (
auto Err = Handler(this->createAbandonedResponseError())) {
745 template <
typename ChannelT,
typename HandlerT>
758 if (
auto Err = C.endReceiveMessage())
760 return Handler(std::move(Result));
766 if (
auto Err = Handler(this->createAbandonedResponseError())) {
777 template <
typename ChannelT,
typename FuncRetT,
typename HandlerT>
779 return llvm::make_unique<ResponseHandlerImpl<ChannelT, FuncRetT, HandlerT>>(
785 template <
typename ClassT,
typename RetT,
typename... ArgTs>
790 : Instance(Instance), Method(Method) {}
792 return (Instance.*Method)(std::move(
Args)...);
806 template <
typename ArgT,
typename... ArgTs>
810 :
ReadArgs<ArgTs...>(Args...), Arg(Arg) {}
813 this->
Arg = std::move(ArgVal);
826 std::lock_guard<std::mutex>
Lock(SeqNoLock);
827 NextSequenceNumber = 0;
828 FreeSequenceNumbers.clear();
834 std::lock_guard<std::mutex>
Lock(SeqNoLock);
835 if (FreeSequenceNumbers.empty())
836 return NextSequenceNumber++;
837 auto SequenceNumber = FreeSequenceNumbers.back();
838 FreeSequenceNumbers.pop_back();
839 return SequenceNumber;
844 std::lock_guard<std::mutex>
Lock(SeqNoLock);
845 FreeSequenceNumbers.push_back(SequenceNumber);
849 std::mutex SeqNoLock;
850 SequenceNumberT NextSequenceNumber = 0;
851 std::vector<SequenceNumberT> FreeSequenceNumbers;
856 template <
template <
class,
class>
class P,
typename T1Tuple,
typename T2Tuple>
859 template <
template <
class,
class>
class P>
862 static const bool value =
true;
865 template <
template <
class,
class>
class P,
typename T,
typename... Ts,
866 typename U,
typename... Us>
869 static const bool value =
874 template <
template <
class,
class>
class P,
typename T1Sig,
typename T2Sig>
880 static_assert(std::tuple_size<T1Tuple>::value >=
881 std::tuple_size<T2Tuple>::value,
882 "Too many arguments to RPC call");
883 static_assert(std::tuple_size<T1Tuple>::value <=
884 std::tuple_size<T2Tuple>::value,
885 "Too few arguments to RPC call");
890 template <
typename ChannelT,
typename WireT,
typename ConcreteT>
895 template <
typename T>
896 static std::true_type
897 check(
typename std::enable_if<
898 std::is_same<decltype(T::serialize(std::declval<ChannelT &>(),
899 std::declval<const ConcreteT &>())),
903 template <
typename>
static std::false_type check(...);
906 static const bool value = decltype(check<S>(0))::value;
909 template <
typename ChannelT,
typename WireT,
typename ConcreteT>
914 template <
typename T>
915 static std::true_type
916 check(
typename std::enable_if<
917 std::is_same<decltype(T::deserialize(std::declval<ChannelT &>(),
918 std::declval<ConcreteT &>())),
922 template <
typename>
static std::false_type check(...);
925 static const bool value = decltype(check<S>(0))::value;
938 template <
typename ImplT,
typename ChannelT,
typename FunctionIdT,
939 typename SequenceNumberT>
944 static const char *
getName() {
return "__orc_rpc$invalid"; }
949 static const char *
getName() {
return "__orc_rpc$response"; }
953 :
public Function<OrcRPCNegotiate, FunctionIdT(std::string)> {
955 static const char *
getName() {
return "__orc_rpc$negotiate"; }
960 template <
typename WireT,
typename ConcreteT>
965 static_assert(value,
"Missing serializer for argument (Can't serialize the " 966 "first template type argument of CanSerializeCheck " 972 template <
typename WireT,
typename ConcreteT>
978 static_assert(value,
"Missing deserializer for argument (Can't deserialize " 979 "the second template type argument of " 980 "CanDeserializeCheck from the first)");
986 : C(C), LazyAutoNegotiation(LazyAutoNegotiation) {
989 ResponseId = FnIdAllocator.getResponseId();
990 RemoteFunctionIds[OrcRPCResponse::getPrototype()] = ResponseId;
993 auto NegotiateId = FnIdAllocator.getNegotiateId();
994 RemoteFunctionIds[OrcRPCNegotiate::getPrototype()] = NegotiateId;
995 Handlers[NegotiateId] = wrapHandler<OrcRPCNegotiate>(
996 [
this](
const std::string &
Name) {
return handleNegotiate(
Name); });
1002 return getRemoteFunctionId<Func>(
true, Retry).takeError();
1010 template <
typename Func,
typename HandlerT,
typename... ArgTs>
1015 void(ArgTs...)>::value,
1020 if (
auto FnIdOrErr = getRemoteFunctionId<Func>(LazyAutoNegotiation,
false))
1025 cantFail(Handler(make_error<ResponseAbandoned>()));
1026 return FnIdOrErr.takeError();
1029 SequenceNumberT SeqNo;
1032 std::lock_guard<std::mutex>
Lock(ResponsesMutex);
1035 SeqNo = SequenceNumberMgr.getSequenceNumber();
1036 assert(!PendingResponses.count(SeqNo) &&
1037 "Sequence number already allocated");
1040 PendingResponses[SeqNo] =
1041 detail::createResponseHandler<ChannelT, typename Func::ReturnType>(
1042 std::move(Handler));
1046 if (
auto Err =
C.startSendMessage(FnId, SeqNo)) {
1047 abandonPendingResponses();
1054 abandonPendingResponses();
1059 if (
auto Err =
C.endSendMessage()) {
1060 abandonPendingResponses();
1069 template <
typename Func,
typename HandlerT,
typename... ArgTs>
1071 if (
auto Err = appendCallAsync<Func>(std::move(Handler), Args...))
1079 SequenceNumberT SeqNo;
1080 if (
auto Err =
C.startReceiveMessage(FnId, SeqNo)) {
1081 abandonPendingResponses();
1084 if (FnId == ResponseId)
1085 return handleResponse(SeqNo);
1086 auto I = Handlers.find(FnId);
1087 if (
I != Handlers.end())
1088 return I->second(
C, SeqNo);
1091 return make_error<BadFunctionCall<FunctionIdT, SequenceNumberT>>(FnId,
1108 template <
typename... ArgTs>
1123 std::lock_guard<std::mutex>
Lock(ResponsesMutex);
1125 for (
auto &KV : PendingResponses)
1126 KV.second->abandon();
1127 PendingResponses.clear();
1128 SequenceNumberMgr.reset();
1133 template <
typename Func>
1135 auto IdItr = LocalFunctionIds.find(Func::getPrototype());
1136 assert(IdItr != LocalFunctionIds.end() &&
1137 "Function does not have a registered handler");
1138 auto HandlerItr = Handlers.find(IdItr->second);
1139 assert(HandlerItr != Handlers.end() &&
1140 "Function does not have a registered handler");
1141 Handlers.erase(HandlerItr);
1152 return FnIdAllocator.getInvalidId();
1157 template <
typename Func,
typename HandlerT>
1165 FunctionIdT NewFnId = FnIdAllocator.template allocate<Func>();
1166 LocalFunctionIds[Func::getPrototype()] = NewFnId;
1167 Handlers[NewFnId] = wrapHandler<Func>(std::move(Handler));
1170 template <
typename Func,
typename HandlerT>
1180 FunctionIdT NewFnId = FnIdAllocator.template allocate<Func>();
1181 LocalFunctionIds[Func::getPrototype()] = NewFnId;
1182 Handlers[NewFnId] = wrapAsyncHandler<Func>(std::move(Handler));
1186 using Handler =
typename decltype(PendingResponses)::mapped_type;
1191 std::unique_lock<std::mutex>
Lock(ResponsesMutex);
1192 auto I = PendingResponses.find(SeqNo);
1194 if (
I != PendingResponses.end()) {
1195 PRHandler = std::move(
I->second);
1196 PendingResponses.erase(
I);
1197 SequenceNumberMgr.releaseSequenceNumber(SeqNo);
1201 abandonPendingResponses();
1208 "If we didn't find a response handler we should have bailed out");
1210 if (
auto Err = PRHandler->handleResponse(
C)) {
1211 abandonPendingResponses();
1219 auto I = LocalFunctionIds.find(Name);
1220 if (
I == LocalFunctionIds.end())
1221 return getInvalidFunctionId();
1226 template <
typename Func>
1228 bool NegotiateIfInvalid) {
1232 auto I = RemoteFunctionIds.find(Func::getPrototype());
1233 if (
I != RemoteFunctionIds.end()) {
1235 if (
I->second != getInvalidFunctionId())
1237 DoNegotiate = NegotiateIfInvalid;
1239 DoNegotiate = NegotiateIfNotInMap;
1244 auto &Impl =
static_cast<ImplT &
>(*this);
1245 if (
auto RemoteIdOrErr =
1246 Impl.template callB<OrcRPCNegotiate>(Func::getPrototype())) {
1247 RemoteFunctionIds[Func::getPrototype()] = *RemoteIdOrErr;
1248 if (*RemoteIdOrErr == getInvalidFunctionId())
1249 return make_error<CouldNotNegotiate>(Func::getPrototype());
1250 return *RemoteIdOrErr;
1252 return RemoteIdOrErr.takeError();
1257 return make_error<CouldNotNegotiate>(Func::getPrototype());
1264 template <
typename Func,
typename HandlerT>
1266 return [
this, Handler](ChannelT &Channel,
1267 SequenceNumberT SeqNo)
mutable -> Error {
1272 auto Args = std::make_shared<ArgsTuple>();
1285 if (
auto Err = Channel.endReceiveMessage())
1290 return detail::respond<FuncReturn>(Channel, ResponseId, SeqNo,
1291 HTraits::unpackAndRun(Handler, *
Args));
1297 template <
typename Func,
typename HandlerT>
1299 return [
this, Handler](ChannelT &Channel,
1300 SequenceNumberT SeqNo)
mutable -> Error {
1306 auto Args = std::make_shared<ArgsTuple>();
1319 if (
auto Err = Channel.endReceiveMessage())
1325 [
this, SeqNo](
typename AHTraits::ResultType RetVal) -> Error {
1326 return detail::respond<FuncReturn>(
C, ResponseId, SeqNo,
1330 return HTraits::unpackAndRunAsync(Handler, Responder, *
Args);
1348 std::map<SequenceNumberT, std::unique_ptr<detail::ResponseHandler<ChannelT>>>
1354 template <
typename ChannelT,
typename FunctionIdT =
uint32_t,
1355 typename SequenceNumberT =
uint32_t>
1358 MultiThreadedRPCEndpoint<ChannelT, FunctionIdT, SequenceNumberT>,
1359 ChannelT, FunctionIdT, SequenceNumberT> {
1364 ChannelT, FunctionIdT, SequenceNumberT>;
1373 template <
typename Func,
typename HandlerT>
1375 return this->
template addHandlerImpl<Func>(std::move(Handler));
1379 template <
typename Func,
typename ClassT,
typename RetT,
typename... ArgTs>
1380 void addHandler(ClassT &Object, RetT (ClassT::*Method)(ArgTs...)) {
1385 template <
typename Func,
typename HandlerT>
1387 return this->
template addAsyncHandlerImpl<Func>(std::move(Handler));
1391 template <
typename Func,
typename ClassT,
typename RetT,
typename... ArgTs>
1393 addAsyncHandler<Func>(
1398 template <
typename Func>
1409 template <
typename Func,
typename... ArgTs>
1412 using ErrorReturn =
typename RTraits::ErrorReturnType;
1413 using ErrorReturnPromise =
typename RTraits::ReturnPromiseType;
1417 auto Promise = std::make_shared<ErrorReturnPromise>();
1418 auto FutureResult = Promise->get_future();
1420 if (
auto Err = this->
template appendCallAsync<Func>(
1421 [Promise](ErrorReturn RetOrErr) {
1422 Promise->set_value(std::move(RetOrErr));
1426 RTraits::consumeAbandoned(FutureResult.get());
1427 return std::move(Err);
1429 return std::move(FutureResult);
1434 template <
typename Func,
typename... ArgTs>
1436 auto Result = appendCallNB<Func>(Args...);
1439 if (
auto Err = this->
C.send()) {
1440 this->abandonPendingResponses();
1442 std::move(Result->get()));
1443 return std::move(Err);
1453 template <
typename Func,
typename... ArgTs,
1457 if (
auto FutureResOrErr = callNB<Func>(Args...))
1458 return FutureResOrErr->get();
1460 return FutureResOrErr.takeError();
1466 if (
auto Err = this->handleOne())
1472 template <
typename ChannelT,
typename FunctionIdT =
uint32_t,
1473 typename SequenceNumberT =
uint32_t>
1476 SingleThreadedRPCEndpoint<ChannelT, FunctionIdT, SequenceNumberT>,
1477 ChannelT, FunctionIdT, SequenceNumberT> {
1482 ChannelT, FunctionIdT, SequenceNumberT>;
1488 template <
typename Func,
typename HandlerT>
1490 return this->
template addHandlerImpl<Func>(std::move(Handler));
1493 template <
typename Func,
typename ClassT,
typename RetT,
typename... ArgTs>
1494 void addHandler(ClassT &Object, RetT (ClassT::*Method)(ArgTs...)) {
1499 template <
typename Func,
typename HandlerT>
1501 return this->
template addAsyncHandlerImpl<Func>(std::move(Handler));
1505 template <
typename Func,
typename ClassT,
typename RetT,
typename... ArgTs>
1507 addAsyncHandler<Func>(
1511 template <
typename Func,
typename... ArgTs,
1515 bool ReceivedResponse =
false;
1523 if (
auto Err = this->
template appendCallAsync<Func>(
1525 Result = std::move(R);
1526 ReceivedResponse =
true;
1532 return std::move(Err);
1535 while (!ReceivedResponse) {
1536 if (
auto Err = this->handleOne()) {
1539 return std::move(Err);
1548 template <
typename RPCClass,
typename Func>
1553 template <
typename HandlerT,
typename... ArgTs>
1555 return Endpoint.template appendCallAsync<Func>(std::move(Handler), Args...);
1563 template <
typename Func,
typename RPCEndpo
intT>
1578 template <
typename AsyncDispatcher,
typename HandlerT,
typename... ArgTs>
1579 Error
call(
const AsyncDispatcher &AsyncDispatch, HandlerT Handler,
1580 const ArgTs &...
Args) {
1586 std::unique_lock<std::mutex>
Lock(M);
1587 ++NumOutstandingCalls;
1595 auto WrappedHandler = [
this, Handler](ArgType
Arg) {
1596 auto Err = Handler(std::move(
Arg));
1597 std::unique_lock<std::mutex>
Lock(M);
1598 --NumOutstandingCalls;
1603 return AsyncDispatch(std::move(WrappedHandler), Args...);
1609 std::unique_lock<std::mutex>
Lock(M);
1610 while (NumOutstandingCalls > 0)
1616 std::condition_variable CV;
1623 template <
typename... Funcs>
1628 template <
typename F>
1631 static const bool value =
false;
1635 template <
typename RPCEndpo
int>
1641 template <
typename Func,
typename... Funcs>
1645 template <
typename F>
1648 static const bool value = std::is_same<F, Func>::value |
1649 APICalls<Funcs...>::template Contains<F>::value;
1652 template <
typename RPCEndpo
int>
1654 if (
auto Err = R.template negotiateFunction<Func>())
1661 template <
typename... InnerFuncs,
typename... Funcs>
1665 template <
typename F>
1668 static const bool value =
1669 APICalls<InnerFuncs...>::template Contains<F>::value |
1670 APICalls<Funcs...>::template Contains<F>::value;
1673 template <
typename RPCEndpo
int>
static Error unpackAndRunAsync(HandlerT &Handler, ResponderT &Responder, std::tuple< TArgTs... > &Args)
Error appendCallAsync(HandlerT Handler, const ArgTs &... Args)
Append a call Func, does not call send on the channel.
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
std::promise< ErrorReturnType > ReturnPromiseType
MultiThreadedRPCEndpoint(ChannelT &C, bool LazyAutoNegotiation)
Type
MessagePack types as defined in the standard, with the exception of Integer being divided into a sign...
detail::ResultTraits< AltRetT >::ErrorReturnType callB(const ArgTs &... Args)
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
void releaseSequenceNumber(SequenceNumberT SequenceNumber)
Error call(const AsyncDispatcher &AsyncDispatch, HandlerT Handler, const ArgTs &... Args)
Make as asynchronous call.
FunctionIdT handleNegotiate(const std::string &Name)
static T getNegotiateId()
void addHandlerImpl(HandlerT Handler)
Add the given handler to the handler map and make it available for autonegotiation and execution...
Error sendAppendedCalls()
static ErrorReturnType createBlankErrorReturnValue()
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
This class represents lattice values for constants.
void addHandler(HandlerT Handler)
std::map< FunctionIdT, WrappedHandlerFn > Handlers
SequenceNumberT getSequenceNumber()
RPCAsyncDispatch(RPCClass &Endpoint)
BadFunctionCall is returned from handleOne when the remote makes a call with an unrecognized function...
std::future< ErrorReturnType > ReturnFutureType
Subclass of Error for the sole purpose of identifying the success path in the type system...
void addHandler(ClassT &Object, RetT(ClassT::*Method)(ArgTs...))
Add a class-method as a handler.
ResponseHandlerImpl(HandlerT Handler)
static Error serializeArgs(ChannelT &C, const CArgTs... CArgs)
static Error sendResult(ChannelT &C, const FunctionIdT &ResponseId, SequenceNumberT SeqNo, Expected< HandlerRetT > ResultOrErr)
void log(raw_ostream &OS) const override
static void consumeAbandoned(ErrorReturnType Err)
BadFunctionCall(FnIdT FnId, SeqNoT SeqNo)
void addAsyncHandler(HandlerT Handler)
ResponseHandlerImpl(HandlerT Handler)
Allows a set of asynchrounous calls to be dispatched, and then waited on as a group.
static Error sendResult(ChannelT &C, const FunctionIdT &ResponseId, SequenceNumberT SeqNo, Error Err)
block Block Frequency true
Expected< NonBlockingCallResult< Func > > appendCallNB(const ArgTs &... Args)
Call Func on Channel C.
Error takeError()
Take ownership of the stored error.
Error handlerLoop()
Handle incoming RPC calls.
Error operator()(ArgT &ArgVal, ArgTs &... ArgVals)
**static detail::ReadArgs< ArgTs... > readArgs(ArgTs &... Args)
Helper for handling setter procedures - this method returns a functor that sets the variables referre...
static Error negotiate(RPCEndpoint &R)
Negotiate all functions in this API.
detail::ResultTraits< AltRetT >::ErrorReturnType callB(const ArgTs &... Args)
Call Func on Channel C.
void abandonPendingResponses()
Abandon all outstanding result handlers.
Expected< NonBlockingCallResult< Func > > callNB(const ArgTs &... Args)
The same as appendCallNBWithSeq, except that it calls C.send() to flush the channel after serializing...
typename FunctionArgsTuple< T2Sig >::Type T2Tuple
Error respond(ChannelT &C, const FunctionIdT &ResponseId, SequenceNumberT SeqNo, Error Err)
RetT operator()(ArgTs &&... Args)
Base class of all fatal RPC errors (those that necessarily result in the termination of the RPC sessi...
amdgpu Simplify well known AMD library false Value Value const Twine & Name
void addAsyncHandler(HandlerT Handler)
RetT(ClassT::*)(ArgTs...) MethodT
std::promise< ErrorReturnType > ReturnPromiseType
std::error_code orcError(OrcErrorCode ErrCode)
InvalidSequenceNumberForResponse(SeqNoT SeqNo)
static ErrorReturnType createBlankErrorReturnValue()
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
void removeHandler()
Remove the handler for the given function.
Error callAsync(HandlerT Handler, const ArgTs &... Args)
WrappedHandlerFn wrapAsyncHandler(HandlerT Handler)
Provides a typedef for a tuple containing the decayed argument types.
MemberFnWrapper(ClassT &Instance, MethodT Method)
Tagged union holding either a T or a Error.
Expected< FunctionIdT > getRemoteFunctionId(bool NegotiateIfNotInMap, bool NegotiateIfInvalid)
Alias for the common case of a sequence of size_ts.
static Error negotiate(RPCEndpoint &R)
Error serializeSeq(ChannelT &C, ArgTs &&... Args)
ResponseHandlerImpl(HandlerT Handler)
Error handleOne()
Handle one incoming call.
Error handleResponse(ChannelT &C) override
static Error deserializeArgs(ChannelT &C, std::tuple< CArgTs... > &Args)
std::tuple< typename std::decay< typename std::remove_reference< ArgTs >::type >::type... > Type
void wait()
Blocks until all calls have been completed and their return value handlers run.
void addHandler(HandlerT Handler)
Add a handler for the given RPC function.
ResponseHandlerImpl(HandlerT Handler)
RetT(ArgTs...) Type
User defined function type.
static const char * getName()
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.
Error handleResponse(SequenceNumberT SeqNo)
std::error_code convertToErrorCode() const override
std::function< Error(ChannelT &, SequenceNumberT)> WrappedHandlerFn
The instances of the Type class are immutable: once they are created, they are never changed...
Asynchronous dispatch for a function on an RPC endpoint.
std::unique_ptr< ResponseHandler< ChannelT > > createResponseHandler(HandlerT H)
This error is returned if the remote does not have a handler installed for the given RPC function...
Allocates RPC function ids during autonegotiation.
std::map< std::string, FunctionIdT > LocalFunctionIds
RetT ReturnType
Return type.
static Error sendResult(ChannelT &C, const FunctionIdT &ResponseId, SequenceNumberT SeqNo, Error Err)
void consumeError(Error Err)
Consume a Error without doing anything.
static const char * getName()
void clearHandlers()
Clear all handlers.
static const char * getName()
RPCConnectionClosed is returned from RPC operations if the RPC connection has already been closed due...
static Error createAbandonedResponseError()
static ErrorSuccess success()
Create a success value.
std::error_code convertToErrorCode() const override
static void consumeAbandoned(ErrorReturnType RetOrErr)
virtual ~ResponseHandler()
const std::string & getSignature() const
Creates a compile-time integer sequence for a parameter pack.
Contains primitive utilities for defining, calling and handling calls to remote procedures.
std::mutex ResponsesMutex
virtual std::error_code convertToErrorCode() const =0
Convert this error to a std::error_code.
std::map< const char *, FunctionIdT > RemoteFunctionIds
Test whether this API contains Function F.
FunctionIdT getInvalidFunctionId() const
WrappedHandlerFn wrapHandler(HandlerT Handler)
Base class for user error types.
RPCEndpointBase(ChannelT &C, bool LazyAutoNegotiation)
Construct an RPC instance on a channel.
Error operator()(HandlerT Handler, const ArgTs &... Args) const
amdgpu Simplify well known AMD library false Value Value * Arg
InvalidSequenceNumberForResponse is returned from handleOne when a response call arrives with a seque...
This non-fatal error will be passed to asynchronous result handlers in place of a result if the conne...
detail::SequenceNumberManager< SequenceNumberT > SequenceNumberMgr
Error handleResponse(ChannelT &C) override
std::future< ErrorReturnType > ReturnFutureType
static Error negotiate(RPCEndpoint &R)
static std::enable_if< std::is_void< typename HandlerTraits< HandlerT >::ReturnType >::value, Error >::type run(HandlerT &Handler, ArgTs &&... Args)
bool isA() const
Check whether one error is a subclass of another.
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.
Utility class for serializing sequences of values of varying types.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Error handleResponse(ChannelT &C) override
A raw_ostream that writes to an std::string.
void addAsyncHandler(ClassT &Object, RetT(ClassT::*Method)(ArgTs...))
Add a class-method as a handler.
static Error sendResult(ChannelT &C, const FunctionIdT &ResponseId, SequenceNumberT SeqNo, Expected< HandlerRetT > ResultOrErr)
static WrappedHandlerReturn< RetT >::Type unpackAndRun(HandlerT &Handler, std::tuple< TArgTs... > &Args)
Lightweight error class with error context and mandatory checking.
void addHandler(ClassT &Object, RetT(ClassT::*Method)(ArgTs...))
typename detail::ResultTraits< typename Func::ReturnType >::ReturnFutureType NonBlockingCallResult
Return type for non-blocking call primitives.
This class implements an extremely fast bulk output stream that can only output to a stream...
std::map< SequenceNumberT, std::unique_ptr< detail::ResponseHandler< ChannelT > > > PendingResponses
print Print MemDeps of function
Convenience class for grouping RPC Functions into APIs that can be negotiated as a block...
void addAsyncHandler(ClassT &Object, RetT(ClassT::*Method)(ArgTs...))
Add a class-method as a handler.
void addAsyncHandlerImpl(HandlerT Handler)
static std::enable_if< !std::is_void< typename HandlerTraits< HandlerT >::ReturnType >::value, typename HandlerTraits< HandlerT >::ReturnType >::type run(HandlerT &Handler, TArgTs... Args)
SingleThreadedRPCEndpoint(ChannelT &C, bool LazyAutoNegotiation)
Error negotiateFunction(bool Retry=false)
Negotiate a function id for Func with the other end of the channel.
ReadArgs(ArgT &Arg, ArgTs &... Args)
Error handleResponse(ChannelT &C) override
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
RPCFunctionIdAllocator< FunctionIdT > FnIdAllocator