17
17
#include < map>
18
18
#include < vector>
19
19
20
+ #include " llvm/ADT/Optional.h"
20
21
#include " llvm/ADT/STLExtras.h"
21
22
#include " llvm/ExecutionEngine/Orc/OrcError.h"
22
23
@@ -60,7 +61,6 @@ template <typename T> class RPCFunctionIdTraits {
60
61
// partially specialized.
61
62
class RPCBase {
62
63
protected:
63
-
64
64
// RPC Function description type.
65
65
//
66
66
// This class provides the information and operations needed to support the
@@ -69,9 +69,12 @@ class RPCBase {
69
69
// betwen the two. Both specializations have the same interface:
70
70
//
71
71
// Id - The function's unique identifier.
72
- // ErrorReturn - The return type for blocking calls.
72
+ // OptionalReturn - The return type for asyncronous calls.
73
+ // ErrorReturn - The return type for synchronous calls.
74
+ // optionalToErrorReturn - Conversion from a valid OptionalReturn to an
75
+ // ErrorReturn.
73
76
// readResult - Deserialize a result from a channel.
74
- // abandon - Abandon a promised result.
77
+ // abandon - Abandon a promised (asynchronous) result.
75
78
// respond - Retun a result on the channel.
76
79
template <typename FunctionIdT, FunctionIdT FuncId, typename FnT>
77
80
class FunctionHelper {};
@@ -88,29 +91,32 @@ class RPCBase {
88
91
89
92
static const FunctionIdT Id = FuncId;
90
93
94
+ typedef Optional<RetT> OptionalReturn;
95
+
91
96
typedef Expected<RetT> ErrorReturn;
92
97
98
+ static ErrorReturn optionalToErrorReturn (OptionalReturn &&V) {
99
+ assert (V && " Return value not available" );
100
+ return std::move (*V);
101
+ }
102
+
93
103
template <typename ChannelT>
94
- static Error readResult (ChannelT &C, std::promise<ErrorReturn > &P) {
104
+ static Error readResult (ChannelT &C, std::promise<OptionalReturn > &P) {
95
105
RetT Val;
96
106
auto Err = deserialize (C, Val);
97
107
auto Err2 = endReceiveMessage (C);
98
108
Err = joinErrors (std::move (Err), std::move (Err2));
99
- if (Err)
100
- return Err;
101
109
110
+ if (Err) {
111
+ P.set_value (OptionalReturn ());
112
+ return Err;
113
+ }
102
114
P.set_value (std::move (Val));
103
115
return Error::success ();
104
116
}
105
117
106
- static void abandon (std::promise<ErrorReturn> &P) {
107
- P.set_value (
108
- make_error<StringError>(" RPC function call failed to return" ,
109
- inconvertibleErrorCode ()));
110
- }
111
-
112
- static void consumeAbandoned (std::future<ErrorReturn> &P) {
113
- consumeError (P.get ().takeError ());
118
+ static void abandon (std::promise<OptionalReturn> &P) {
119
+ P.set_value (OptionalReturn ());
114
120
}
115
121
116
122
template <typename ChannelT, typename SequenceNumberT>
@@ -142,24 +148,22 @@ class RPCBase {
142
148
143
149
static const FunctionIdT Id = FuncId;
144
150
151
+ typedef bool OptionalReturn;
145
152
typedef Error ErrorReturn;
146
153
154
+ static ErrorReturn optionalToErrorReturn (OptionalReturn &&V) {
155
+ assert (V && " Return value not available" );
156
+ return Error::success ();
157
+ }
158
+
147
159
template <typename ChannelT>
148
- static Error readResult (ChannelT &C, std::promise<ErrorReturn > &P) {
160
+ static Error readResult (ChannelT &C, std::promise<OptionalReturn > &P) {
149
161
// Void functions don't have anything to deserialize, so we're good.
150
- P.set_value (Error::success () );
162
+ P.set_value (true );
151
163
return endReceiveMessage (C);
152
164
}
153
165
154
- static void abandon (std::promise<ErrorReturn> &P) {
155
- P.set_value (
156
- make_error<StringError>(" RPC function call failed to return" ,
157
- inconvertibleErrorCode ()));
158
- }
159
-
160
- static void consumeAbandoned (std::future<ErrorReturn> &P) {
161
- consumeError (P.get ());
162
- }
166
+ static void abandon (std::promise<OptionalReturn> &P) { P.set_value (false ); }
163
167
164
168
template <typename ChannelT, typename SequenceNumberT>
165
169
static Error respond (ChannelT &C, SequenceNumberT SeqNo,
@@ -374,118 +378,94 @@ class RPC : public RPCBase {
374
378
template <FunctionIdT FuncId, typename FnT>
375
379
using Function = FunctionHelper<FunctionIdT, FuncId, FnT>;
376
380
377
- // / Return type for non-blocking call primitives.
381
+ // / Return type for asynchronous call primitives.
378
382
template <typename Func>
379
- using NonBlockingCallResult = std::future<typename Func::ErrorReturn >;
383
+ using AsyncCallResult = std::future<typename Func::OptionalReturn >;
380
384
381
- // / Return type for non-blocking call-with-seq primitives.
385
+ // / Return type for asynchronous call-with-seq primitives.
382
386
template <typename Func>
383
- using NonBlockingCallWithSeqResult =
384
- std::pair<NonBlockingCallResult< Func>, SequenceNumberT>;
387
+ using AsyncCallWithSeqResult =
388
+ std::pair<std::future< typename Func::OptionalReturn >, SequenceNumberT>;
385
389
386
- // / Call Func on Channel C. Does not block, does not call send. Returns a pair
387
- // / of a future result and the sequence number assigned to the result.
390
+ // / Serialize Args... to channel C, but do not call C.send().
391
+ // /
392
+ // / Returns an error (on serialization failure) or a pair of:
393
+ // / (1) A future Optional<T> (or future<bool> for void functions), and
394
+ // / (2) A sequence number.
388
395
// /
389
396
// / This utility function is primarily used for single-threaded mode support,
390
397
// / where the sequence number can be used to wait for the corresponding
391
- // / result. In multi-threaded mode the appendCallNB method, which does not
398
+ // / result. In multi-threaded mode the appendCallAsync method, which does not
392
399
// / return the sequence numeber, should be preferred.
393
400
template <typename Func, typename ... ArgTs>
394
- Expected<NonBlockingCallWithSeqResult <Func>>
395
- appendCallNBWithSeq (ChannelT &C, const ArgTs &... Args) {
401
+ Expected<AsyncCallWithSeqResult <Func>>
402
+ appendCallAsyncWithSeq (ChannelT &C, const ArgTs &... Args) {
396
403
auto SeqNo = SequenceNumberMgr.getSequenceNumber ();
397
- std::promise<typename Func::ErrorReturn > Promise;
404
+ std::promise<typename Func::OptionalReturn > Promise;
398
405
auto Result = Promise.get_future ();
399
406
OutstandingResults[SeqNo] =
400
407
createOutstandingResult<Func>(std::move (Promise));
401
408
402
409
if (auto Err = CallHelper<ChannelT, SequenceNumberT, Func>::call (C, SeqNo,
403
410
Args...)) {
404
411
abandonOutstandingResults ();
405
- Func::consumeAbandoned (Result);
406
412
return std::move (Err);
407
413
} else
408
- return NonBlockingCallWithSeqResult <Func>(std::move (Result), SeqNo);
414
+ return AsyncCallWithSeqResult <Func>(std::move (Result), SeqNo);
409
415
}
410
416
411
- // / The same as appendCallNBWithSeq , except that it calls C.send() to
417
+ // / The same as appendCallAsyncWithSeq , except that it calls C.send() to
412
418
// / flush the channel after serializing the call.
413
419
template <typename Func, typename ... ArgTs>
414
- Expected<NonBlockingCallWithSeqResult <Func>>
415
- callNBWithSeq (ChannelT &C, const ArgTs &... Args) {
416
- auto Result = appendCallNBWithSeq <Func>(C, Args...);
420
+ Expected<AsyncCallWithSeqResult <Func>>
421
+ callAsyncWithSeq (ChannelT &C, const ArgTs &... Args) {
422
+ auto Result = appendCallAsyncWithSeq <Func>(C, Args...);
417
423
if (!Result)
418
424
return Result;
419
425
if (auto Err = C.send ()) {
420
426
abandonOutstandingResults ();
421
- Func::consumeAbandoned (Result->first );
422
427
return std::move (Err);
423
428
}
424
429
return Result;
425
430
}
426
431
427
432
// / Serialize Args... to channel C, but do not call send.
428
433
// / Returns an error if serialization fails, otherwise returns a
429
- // / std::future<Expected <T>> (or a future<Error > for void functions).
434
+ // / std::future<Optional <T>> (or a future<bool > for void functions).
430
435
template <typename Func, typename ... ArgTs>
431
- Expected<NonBlockingCallResult <Func>> appendCallNB (ChannelT &C,
432
- const ArgTs &... Args) {
433
- auto FutureResAndSeqOrErr = appendCallNBWithSeq <Func>(C, Args...);
434
- if (FutureResAndSeqOrErr )
435
- return std::move (FutureResAndSeqOrErr ->first );
436
- return FutureResAndSeqOrErr .getError ();
436
+ Expected<AsyncCallResult <Func>> appendCallAsync (ChannelT &C,
437
+ const ArgTs &... Args) {
438
+ auto ResAndSeqOrErr = appendCallAsyncWithSeq <Func>(C, Args...);
439
+ if (ResAndSeqOrErr )
440
+ return std::move (ResAndSeqOrErr ->first );
441
+ return ResAndSeqOrErr .getError ();
437
442
}
438
443
439
- // / The same as appendCallNB , except that it calls C.send to flush the
444
+ // / The same as appendCallAsync , except that it calls C.send to flush the
440
445
// / channel after serializing the call.
441
446
template <typename Func, typename ... ArgTs>
442
- Expected<NonBlockingCallResult<Func>> callNB (ChannelT &C,
443
- const ArgTs &... Args) {
444
- auto FutureResAndSeqOrErr = callNBWithSeq<Func>(C, Args...);
445
- if (FutureResAndSeqOrErr)
446
- return std::move (FutureResAndSeqOrErr->first );
447
- return FutureResAndSeqOrErr.getError ();
448
- }
449
-
450
- // / Call Func on Channel C. Blocks waiting for a result. Returns an Error
451
- // / for void functions or an Expected<T> for functions returning a T.
452
- // /
453
- // / This function is for use in threaded code where another thread is
454
- // / handling responses and incoming calls.
455
- template <typename Func, typename ... ArgTs>
456
- typename Func::ErrorReturn callB (ChannelT &C, const ArgTs &... Args) {
457
- if (auto FutureResOrErr = callNBWithSeq (C, Args...)) {
458
- if (auto Err = C.send ()) {
459
- abandonOutstandingResults ();
460
- Func::consumeAbandoned (*FutureResOrErr);
461
- return std::move (Err);
462
- }
463
- return FutureResOrErr->get ();
464
- } else
465
- return FutureResOrErr.takeError ();
447
+ Expected<AsyncCallResult<Func>> callAsync (ChannelT &C,
448
+ const ArgTs &... Args) {
449
+ auto ResAndSeqOrErr = callAsyncWithSeq<Func>(C, Args...);
450
+ if (ResAndSeqOrErr)
451
+ return std::move (ResAndSeqOrErr->first );
452
+ return ResAndSeqOrErr.getError ();
466
453
}
467
454
468
- // / Call Func on Channel C. Block waiting for a result. While blocked, run
469
- // / HandleOther to handle incoming calls (Response calls will be handled
470
- // / implicitly before calling HandleOther). Returns an Error for void
471
- // / functions or an Expected<T> for functions returning a T.
472
- // /
473
- // / This function is for use in single threaded mode when the calling thread
474
- // / must act as both sender and receiver.
455
+ // / This can be used in single-threaded mode.
475
456
template <typename Func, typename HandleFtor, typename ... ArgTs>
476
457
typename Func::ErrorReturn
477
458
callSTHandling (ChannelT &C, HandleFtor &HandleOther, const ArgTs &... Args) {
478
- if (auto ResultAndSeqNoOrErr = callNBWithSeq <Func>(C, Args...)) {
459
+ if (auto ResultAndSeqNoOrErr = callAsyncWithSeq <Func>(C, Args...)) {
479
460
auto &ResultAndSeqNo = *ResultAndSeqNoOrErr;
480
461
if (auto Err = waitForResult (C, ResultAndSeqNo.second , HandleOther))
481
462
return std::move (Err);
482
- return ResultAndSeqNo.first .get ();
463
+ return Func::optionalToErrorReturn ( ResultAndSeqNo.first .get () );
483
464
} else
484
465
return ResultAndSeqNoOrErr.takeError ();
485
466
}
486
467
487
- // / Call Func on Channel C. Block waiting for a result. Returns an Error for
488
- // / void functions or an Expected<T> for functions returning a T.
468
+ // This can be used in single-threaded mode.
489
469
template <typename Func, typename ... ArgTs>
490
470
typename Func::ErrorReturn callST (ChannelT &C, const ArgTs &... Args) {
491
471
return callSTHandling<Func>(C, handleNone, Args...);
@@ -676,21 +656,21 @@ class RPC : public RPCBase {
676
656
class OutstandingResultImpl : public OutstandingResult {
677
657
private:
678
658
public:
679
- OutstandingResultImpl (std::promise<typename Func::ErrorReturn > &&P)
659
+ OutstandingResultImpl (std::promise<typename Func::OptionalReturn > &&P)
680
660
: P(std::move(P)) {}
681
661
682
662
Error readResult (ChannelT &C) override { return Func::readResult (C, P); }
683
663
684
664
void abandon () override { Func::abandon (P); }
685
665
686
666
private:
687
- std::promise<typename Func::ErrorReturn > P;
667
+ std::promise<typename Func::OptionalReturn > P;
688
668
};
689
669
690
670
// Create an outstanding result for the given function.
691
671
template <typename Func>
692
672
std::unique_ptr<OutstandingResult>
693
- createOutstandingResult (std::promise<typename Func::ErrorReturn > &&P) {
673
+ createOutstandingResult (std::promise<typename Func::OptionalReturn > &&P) {
694
674
return llvm::make_unique<OutstandingResultImpl<Func>>(std::move (P));
695
675
}
696
676
0 commit comments