Skip to content

Commit 9e15636

Browse files
committed
[ORC][RPC] Reword 'async' to 'non-blocking' to better reflect call primitive
behaviors, and add a callB (blacking call) primitive. callB is a blocking call primitive for threaded code where the RPC responses are being processed on a separate thread. (For single threaded code callST should continue to be used instead). No unit test yet: Last time I commited a threaded unit test it deadlocked on one of the s390x builders. I'll try to re-enable that test first, and add a new test if I can sort out the deadlock issue. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@280051 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent c1d8a15 commit 9e15636

File tree

2 files changed

+70
-38
lines changed

2 files changed

+70
-38
lines changed

include/llvm/ExecutionEngine/Orc/RPCUtils.h

+67-35
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ class RPCBase {
7171
// Id - The function's unique identifier.
7272
// ErrorReturn - The return type for blocking calls.
7373
// readResult - Deserialize a result from a channel.
74-
// abandon - Abandon a promised (asynchronous) result.
74+
// abandon - Abandon a promised result.
7575
// respond - Retun a result on the channel.
7676
template <typename FunctionIdT, FunctionIdT FuncId, typename FnT>
7777
class FunctionHelper {};
@@ -109,6 +109,10 @@ class RPCBase {
109109
inconvertibleErrorCode()));
110110
}
111111

112+
static void consumeAbandoned(std::future<ErrorReturn> &P) {
113+
consumeError(P.get().takeError());
114+
}
115+
112116
template <typename ChannelT, typename SequenceNumberT>
113117
static Error respond(ChannelT &C, SequenceNumberT SeqNo,
114118
ErrorReturn &Result) {
@@ -153,6 +157,10 @@ class RPCBase {
153157
inconvertibleErrorCode()));
154158
}
155159

160+
static void consumeAbandoned(std::future<ErrorReturn> &P) {
161+
consumeError(P.get());
162+
}
163+
156164
template <typename ChannelT, typename SequenceNumberT>
157165
static Error respond(ChannelT &C, SequenceNumberT SeqNo,
158166
ErrorReturn &Result) {
@@ -366,28 +374,25 @@ class RPC : public RPCBase {
366374
template <FunctionIdT FuncId, typename FnT>
367375
using Function = FunctionHelper<FunctionIdT, FuncId, FnT>;
368376

369-
/// Return type for asynchronous call primitives.
377+
/// Return type for non-blocking call primitives.
370378
template <typename Func>
371-
using AsyncCallResult = std::future<typename Func::ErrorReturn>;
379+
using NonBlockingCallResult = std::future<typename Func::ErrorReturn>;
372380

373-
/// Return type for asynchronous call-with-seq primitives.
381+
/// Return type for non-blocking call-with-seq primitives.
374382
template <typename Func>
375-
using AsyncCallWithSeqResult =
376-
std::pair<AsyncCallResult<Func>, SequenceNumberT>;
383+
using NonBlockingCallWithSeqResult =
384+
std::pair<NonBlockingCallResult<Func>, SequenceNumberT>;
377385

378-
/// Serialize Args... to channel C, but do not call C.send().
379-
///
380-
/// Returns an error (on serialization failure) or a pair of:
381-
/// (1) A future Expected<T> (or future<Error> for void functions), and
382-
/// (2) A sequence number.
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.
383388
///
384389
/// This utility function is primarily used for single-threaded mode support,
385390
/// where the sequence number can be used to wait for the corresponding
386-
/// result. In multi-threaded mode the appendCallAsync method, which does not
391+
/// result. In multi-threaded mode the appendCallNB method, which does not
387392
/// return the sequence numeber, should be preferred.
388393
template <typename Func, typename... ArgTs>
389-
Expected<AsyncCallWithSeqResult<Func>>
390-
appendCallAsyncWithSeq(ChannelT &C, const ArgTs &... Args) {
394+
Expected<NonBlockingCallWithSeqResult<Func>>
395+
appendCallNBWithSeq(ChannelT &C, const ArgTs &... Args) {
391396
auto SeqNo = SequenceNumberMgr.getSequenceNumber();
392397
std::promise<typename Func::ErrorReturn> Promise;
393398
auto Result = Promise.get_future();
@@ -397,21 +402,23 @@ class RPC : public RPCBase {
397402
if (auto Err = CallHelper<ChannelT, SequenceNumberT, Func>::call(C, SeqNo,
398403
Args...)) {
399404
abandonOutstandingResults();
405+
Func::consumeAbandoned(Result);
400406
return std::move(Err);
401407
} else
402-
return AsyncCallWithSeqResult<Func>(std::move(Result), SeqNo);
408+
return NonBlockingCallWithSeqResult<Func>(std::move(Result), SeqNo);
403409
}
404410

405-
/// The same as appendCallAsyncWithSeq, except that it calls C.send() to
411+
/// The same as appendCallNBWithSeq, except that it calls C.send() to
406412
/// flush the channel after serializing the call.
407413
template <typename Func, typename... ArgTs>
408-
Expected<AsyncCallWithSeqResult<Func>>
409-
callAsyncWithSeq(ChannelT &C, const ArgTs &... Args) {
410-
auto Result = appendCallAsyncWithSeq<Func>(C, Args...);
414+
Expected<NonBlockingCallWithSeqResult<Func>>
415+
callNBWithSeq(ChannelT &C, const ArgTs &... Args) {
416+
auto Result = appendCallNBWithSeq<Func>(C, Args...);
411417
if (!Result)
412418
return Result;
413419
if (auto Err = C.send()) {
414420
abandonOutstandingResults();
421+
Func::consumeAbandoned(Result->first);
415422
return std::move(Err);
416423
}
417424
return Result;
@@ -421,30 +428,54 @@ class RPC : public RPCBase {
421428
/// Returns an error if serialization fails, otherwise returns a
422429
/// std::future<Expected<T>> (or a future<Error> for void functions).
423430
template <typename Func, typename... ArgTs>
424-
Expected<AsyncCallResult<Func>> appendCallAsync(ChannelT &C,
425-
const ArgTs &... Args) {
426-
auto ResAndSeqOrErr = appendCallAsyncWithSeq<Func>(C, Args...);
427-
if (ResAndSeqOrErr)
428-
return std::move(ResAndSeqOrErr->first);
429-
return ResAndSeqOrErr.getError();
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();
430437
}
431438

432-
/// The same as appendCallAsync, except that it calls C.send to flush the
439+
/// The same as appendCallNB, except that it calls C.send to flush the
433440
/// channel after serializing the call.
434441
template <typename Func, typename... ArgTs>
435-
Expected<AsyncCallResult<Func>> callAsync(ChannelT &C,
436-
const ArgTs &... Args) {
437-
auto ResAndSeqOrErr = callAsyncWithSeq<Func>(C, Args...);
438-
if (ResAndSeqOrErr)
439-
return std::move(ResAndSeqOrErr->first);
440-
return ResAndSeqOrErr.getError();
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();
441466
}
442467

443-
/// This can be used in single-threaded mode.
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.
444475
template <typename Func, typename HandleFtor, typename... ArgTs>
445476
typename Func::ErrorReturn
446477
callSTHandling(ChannelT &C, HandleFtor &HandleOther, const ArgTs &... Args) {
447-
if (auto ResultAndSeqNoOrErr = callAsyncWithSeq<Func>(C, Args...)) {
478+
if (auto ResultAndSeqNoOrErr = callNBWithSeq<Func>(C, Args...)) {
448479
auto &ResultAndSeqNo = *ResultAndSeqNoOrErr;
449480
if (auto Err = waitForResult(C, ResultAndSeqNo.second, HandleOther))
450481
return std::move(Err);
@@ -453,7 +484,8 @@ class RPC : public RPCBase {
453484
return ResultAndSeqNoOrErr.takeError();
454485
}
455486

456-
// This can be used in single-threaded mode.
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.
457489
template <typename Func, typename... ArgTs>
458490
typename Func::ErrorReturn callST(ChannelT &C, const ArgTs &... Args) {
459491
return callSTHandling<Func>(C, handleNone, Args...);

unittests/ExecutionEngine/Orc/RPCUtilsTest.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ TEST_F(DummyRPC, TestAsyncVoidBool) {
8383
QueueChannel C2(Q2, Q1);
8484

8585
// Make an async call.
86-
auto ResOrErr = callAsyncWithSeq<VoidBool>(C1, true);
86+
auto ResOrErr = callNBWithSeq<VoidBool>(C1, true);
8787
EXPECT_TRUE(!!ResOrErr) << "Simple call over queue failed";
8888

8989
{
@@ -112,7 +112,7 @@ TEST_F(DummyRPC, TestAsyncIntInt) {
112112
QueueChannel C2(Q2, Q1);
113113

114114
// Make an async call.
115-
auto ResOrErr = callAsyncWithSeq<IntInt>(C1, 21);
115+
auto ResOrErr = callNBWithSeq<IntInt>(C1, 21);
116116
EXPECT_TRUE(!!ResOrErr) << "Simple call over queue failed";
117117

118118
{
@@ -143,7 +143,7 @@ TEST_F(DummyRPC, TestSerialization) {
143143

144144
// Make a call to Proc1.
145145
std::vector<int> v({42, 7});
146-
auto ResOrErr = callAsyncWithSeq<AllTheTypes>(
146+
auto ResOrErr = callNBWithSeq<AllTheTypes>(
147147
C1, -101, 250, -10000, 10000, -1000000000, 1000000000, -10000000000,
148148
10000000000, true, "foo", v);
149149
EXPECT_TRUE(!!ResOrErr) << "Big (serialization test) call over queue failed";

0 commit comments

Comments
 (0)