<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Jan 11, 2016 at 10:48 PM, Lang Hames via llvm-commits <span dir="ltr"><<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: lhames<br>
Date: Tue Jan 12 00:48:52 2016<br>
New Revision: 257452<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=257452&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=257452&view=rev</a><br>
Log:<br>
[Orc] Add overloads of RPC::handle and RPC::expect that take member functions as<br>
handlers.<br>
<br>
It is expected that RPC handlers will usually be member functions. Accepting them<br>
directly in handle and expect allows for the remove of a lot of lambdas an<br>
explicit error variables.<br>
<br>
This patch also uses this new feature to substantially tidy up the<br>
OrcRemoteTargetServer class.<br>
<br>
Modified:<br>
llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h<br>
llvm/trunk/include/llvm/ExecutionEngine/Orc/RPCUtils.h<br>
<br>
Modified: llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h?rev=257452&r1=257451&r2=257452&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h?rev=257452&r1=257451&r2=257452&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h (original)<br>
+++ llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h Tue Jan 12 00:48:52 2016<br>
@@ -43,41 +43,54 @@ public:<br>
}<br>
<br>
std::error_code handleKnownProcedure(JITProcId Id) {<br>
+ typedef OrcRemoteTargetServer ThisT;<br>
+<br>
DEBUG(dbgs() << "Handling known proc: " << getJITProcIdName(Id) << "\n");<br>
<br>
switch (Id) {<br>
case CallIntVoidId:<br>
- return handleCallIntVoid();<br>
+ return handle<CallIntVoid>(Channel, *this, &ThisT::handleCallIntVoid);<br></blockquote><div><br></div><div>Might be able to stamp this switch out with a macro/.def file too.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
case CallMainId:<br>
- return handleCallMain();<br>
+ return handle<CallMain>(Channel, *this, &ThisT::handleCallMain);<br>
case CallVoidVoidId:<br>
- return handleCallVoidVoid();<br>
+ return handle<CallVoidVoid>(Channel, *this, &ThisT::handleCallVoidVoid);<br>
case CreateRemoteAllocatorId:<br>
- return handleCreateRemoteAllocator();<br>
+ return handle<CreateRemoteAllocator>(Channel, *this,<br>
+ &ThisT::handleCreateRemoteAllocator);<br>
case CreateIndirectStubsOwnerId:<br>
- return handleCreateIndirectStubsOwner();<br>
+ return handle<CreateIndirectStubsOwner>(<br>
+ Channel, *this, &ThisT::handleCreateIndirectStubsOwner);<br>
case DestroyRemoteAllocatorId:<br>
- return handleDestroyRemoteAllocator();<br>
+ return handle<DestroyRemoteAllocator>(<br>
+ Channel, *this, &ThisT::handleDestroyRemoteAllocator);<br>
+ case DestroyIndirectStubsOwnerId:<br>
+ return handle<DestroyIndirectStubsOwner>(<br>
+ Channel, *this, &ThisT::handleDestroyIndirectStubsOwner);<br>
case EmitIndirectStubsId:<br>
- return handleEmitIndirectStubs();<br>
+ return handle<EmitIndirectStubs>(Channel, *this,<br>
+ &ThisT::handleEmitIndirectStubs);<br>
case EmitResolverBlockId:<br>
- return handleEmitResolverBlock();<br>
+ return handle<EmitResolverBlock>(Channel, *this,<br>
+ &ThisT::handleEmitResolverBlock);<br>
case EmitTrampolineBlockId:<br>
- return handleEmitTrampolineBlock();<br>
+ return handle<EmitTrampolineBlock>(Channel, *this,<br>
+ &ThisT::handleEmitTrampolineBlock);<br>
case GetSymbolAddressId:<br>
- return handleGetSymbolAddress();<br>
+ return handle<GetSymbolAddress>(Channel, *this,<br>
+ &ThisT::handleGetSymbolAddress);<br>
case GetRemoteInfoId:<br>
- return handleGetRemoteInfo();<br>
+ return handle<GetRemoteInfo>(Channel, *this, &ThisT::handleGetRemoteInfo);<br>
case ReadMemId:<br>
- return handleReadMem();<br>
+ return handle<ReadMem>(Channel, *this, &ThisT::handleReadMem);<br>
case ReserveMemId:<br>
- return handleReserveMem();<br>
+ return handle<ReserveMem>(Channel, *this, &ThisT::handleReserveMem);<br>
case SetProtectionsId:<br>
- return handleSetProtections();<br>
+ return handle<SetProtections>(Channel, *this,<br>
+ &ThisT::handleSetProtections);<br>
case WriteMemId:<br>
- return handleWriteMem();<br>
+ return handle<WriteMem>(Channel, *this, &ThisT::handleWriteMem);<br>
case WritePtrId:<br>
- return handleWritePtr();<br>
+ return handle<WritePtr>(Channel, *this, &ThisT::handleWritePtr);<br>
default:<br>
return orcError(OrcErrorCode::UnexpectedRPCCall);<br>
}<br>
@@ -160,16 +173,10 @@ private:<br>
return CompiledFnAddr;<br>
}<br>
<br>
- std::error_code handleCallIntVoid() {<br>
+ std::error_code handleCallIntVoid(TargetAddress Addr) {<br>
typedef int (*IntVoidFnTy)();<br>
-<br>
- IntVoidFnTy Fn = nullptr;<br>
- if (std::error_code EC =<br>
- handle<CallIntVoid>(Channel, [&](TargetAddress Addr) {<br>
- Fn = reinterpret_cast<IntVoidFnTy>(static_cast<uintptr_t>(Addr));<br>
- return std::error_code();<br>
- }))<br>
- return EC;<br>
+ IntVoidFnTy Fn =<br>
+ reinterpret_cast<IntVoidFnTy>(static_cast<uintptr_t>(Addr));<br>
<br>
DEBUG(dbgs() << " Calling "<br>
<< reinterpret_cast<void *>(reinterpret_cast<intptr_t>(Fn))<br>
@@ -180,19 +187,11 @@ private:<br>
return call<CallIntVoidResponse>(Channel, Result);<br>
}<br>
<br>
- std::error_code handleCallMain() {<br>
+ std::error_code handleCallMain(TargetAddress Addr,<br>
+ std::vector<std::string> Args) {<br>
typedef int (*MainFnTy)(int, const char *[]);<br>
<br>
- MainFnTy Fn = nullptr;<br>
- std::vector<std::string> Args;<br>
- if (std::error_code EC = handle<CallMain>(<br>
- Channel, [&](TargetAddress Addr, std::vector<std::string> &A) {<br>
- Fn = reinterpret_cast<MainFnTy>(static_cast<uintptr_t>(Addr));<br>
- Args = std::move(A);<br>
- return std::error_code();<br>
- }))<br>
- return EC;<br>
-<br>
+ MainFnTy Fn = reinterpret_cast<MainFnTy>(static_cast<uintptr_t>(Addr));<br>
int ArgC = Args.size() + 1;<br>
int Idx = 1;<br>
std::unique_ptr<const char *[]> ArgV(new const char *[ArgC + 1]);<br>
@@ -207,16 +206,10 @@ private:<br>
return call<CallMainResponse>(Channel, Result);<br>
}<br>
<br>
- std::error_code handleCallVoidVoid() {<br>
+ std::error_code handleCallVoidVoid(TargetAddress Addr) {<br>
typedef void (*VoidVoidFnTy)();<br>
-<br>
- VoidVoidFnTy Fn = nullptr;<br>
- if (std::error_code EC =<br>
- handle<CallIntVoid>(Channel, [&](TargetAddress Addr) {<br>
- Fn = reinterpret_cast<VoidVoidFnTy>(static_cast<uintptr_t>(Addr));<br>
- return std::error_code();<br>
- }))<br>
- return EC;<br>
+ VoidVoidFnTy Fn =<br>
+ reinterpret_cast<VoidVoidFnTy>(static_cast<uintptr_t>(Addr));<br>
<br>
DEBUG(dbgs() << " Calling " << reinterpret_cast<void *>(Fn) << "\n");<br>
Fn();<br>
@@ -225,66 +218,48 @@ private:<br>
return call<CallVoidVoidResponse>(Channel);<br>
}<br>
<br>
- std::error_code handleCreateRemoteAllocator() {<br>
- return handle<CreateRemoteAllocator>(<br>
- Channel, [&](ResourceIdMgr::ResourceId Id) {<br>
- auto I = Allocators.find(Id);<br>
- if (I != Allocators.end())<br>
- return orcError(OrcErrorCode::RemoteAllocatorIdAlreadyInUse);<br>
- DEBUG(dbgs() << " Created allocator " << Id << "\n");<br>
- Allocators[Id] = Allocator();<br>
- return std::error_code();<br>
- });<br>
- }<br>
-<br>
- std::error_code handleCreateIndirectStubsOwner() {<br>
- return handle<CreateIndirectStubsOwner>(<br>
- Channel, [&](ResourceIdMgr::ResourceId Id) {<br>
- auto I = IndirectStubsOwners.find(Id);<br>
- if (I != IndirectStubsOwners.end())<br>
- return orcError(<br>
- OrcErrorCode::RemoteIndirectStubsOwnerIdAlreadyInUse);<br>
- DEBUG(dbgs() << " Create indirect stubs owner " << Id << "\n");<br>
- IndirectStubsOwners[Id] = ISBlockOwnerList();<br>
- return std::error_code();<br>
- });<br>
- }<br>
-<br>
- std::error_code handleDestroyRemoteAllocator() {<br>
- return handle<DestroyRemoteAllocator>(<br>
- Channel, [&](ResourceIdMgr::ResourceId Id) {<br>
- auto I = Allocators.find(Id);<br>
- if (I == Allocators.end())<br>
- return orcError(OrcErrorCode::RemoteAllocatorDoesNotExist);<br>
- Allocators.erase(I);<br>
- DEBUG(dbgs() << " Destroyed allocator " << Id << "\n");<br>
- return std::error_code();<br>
- });<br>
- }<br>
-<br>
- std::error_code handleDestroyIndirectStubsOwner() {<br>
- return handle<DestroyIndirectStubsOwner>(<br>
- Channel, [&](ResourceIdMgr::ResourceId Id) {<br>
- auto I = IndirectStubsOwners.find(Id);<br>
- if (I == IndirectStubsOwners.end())<br>
- return orcError(OrcErrorCode::RemoteIndirectStubsOwnerDoesNotExist);<br>
- IndirectStubsOwners.erase(I);<br>
- return std::error_code();<br>
- });<br>
- }<br>
-<br>
- std::error_code handleEmitIndirectStubs() {<br>
- ResourceIdMgr::ResourceId ISOwnerId = ~0U;<br>
- uint32_t NumStubsRequired = 0;<br>
-<br>
- if (auto EC = handle<EmitIndirectStubs>(<br>
- Channel, readArgs(ISOwnerId, NumStubsRequired)))<br>
- return EC;<br>
+ std::error_code handleCreateRemoteAllocator(ResourceIdMgr::ResourceId Id) {<br>
+ auto I = Allocators.find(Id);<br>
+ if (I != Allocators.end())<br>
+ return orcError(OrcErrorCode::RemoteAllocatorIdAlreadyInUse);<br>
+ DEBUG(dbgs() << " Created allocator " << Id << "\n");<br>
+ Allocators[Id] = Allocator();<br>
+ return std::error_code();<br>
+ }<br>
+<br>
+ std::error_code handleCreateIndirectStubsOwner(ResourceIdMgr::ResourceId Id) {<br>
+ auto I = IndirectStubsOwners.find(Id);<br>
+ if (I != IndirectStubsOwners.end())<br>
+ return orcError(OrcErrorCode::RemoteIndirectStubsOwnerIdAlreadyInUse);<br>
+ DEBUG(dbgs() << " Create indirect stubs owner " << Id << "\n");<br>
+ IndirectStubsOwners[Id] = ISBlockOwnerList();<br>
+ return std::error_code();<br>
+ }<br>
+<br>
+ std::error_code handleDestroyRemoteAllocator(ResourceIdMgr::ResourceId Id) {<br>
+ auto I = Allocators.find(Id);<br>
+ if (I == Allocators.end())<br>
+ return orcError(OrcErrorCode::RemoteAllocatorDoesNotExist);<br>
+ Allocators.erase(I);<br>
+ DEBUG(dbgs() << " Destroyed allocator " << Id << "\n");<br>
+ return std::error_code();<br>
+ }<br>
+<br>
+ std::error_code<br>
+ handleDestroyIndirectStubsOwner(ResourceIdMgr::ResourceId Id) {<br>
+ auto I = IndirectStubsOwners.find(Id);<br>
+ if (I == IndirectStubsOwners.end())<br>
+ return orcError(OrcErrorCode::RemoteIndirectStubsOwnerDoesNotExist);<br>
+ IndirectStubsOwners.erase(I);<br>
+ return std::error_code();<br>
+ }<br>
<br>
- DEBUG(dbgs() << " ISMgr " << ISOwnerId << " request " << NumStubsRequired<br>
+ std::error_code handleEmitIndirectStubs(ResourceIdMgr::ResourceId Id,<br>
+ uint32_t NumStubsRequired) {<br>
+ DEBUG(dbgs() << " ISMgr " << Id << " request " << NumStubsRequired<br>
<< " stubs.\n");<br>
<br>
- auto StubOwnerItr = IndirectStubsOwners.find(ISOwnerId);<br>
+ auto StubOwnerItr = IndirectStubsOwners.find(Id);<br>
if (StubOwnerItr == IndirectStubsOwners.end())<br>
return orcError(OrcErrorCode::RemoteIndirectStubsOwnerDoesNotExist);<br>
<br>
@@ -307,9 +282,6 @@ private:<br>
}<br>
<br>
std::error_code handleEmitResolverBlock() {<br>
- if (auto EC = handle<EmitResolverBlock>(Channel, doNothing))<br>
- return EC;<br>
-<br>
std::error_code EC;<br>
ResolverBlock = sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory(<br>
TargetT::ResolverCodeSize, nullptr,<br>
@@ -326,11 +298,7 @@ private:<br>
}<br>
<br>
std::error_code handleEmitTrampolineBlock() {<br>
- if (auto EC = handle<EmitTrampolineBlock>(Channel, doNothing))<br>
- return EC;<br>
-<br>
std::error_code EC;<br>
-<br>
auto TrampolineBlock =<br>
sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory(<br>
sys::Process::getPageSize(), nullptr,<br>
@@ -358,21 +326,14 @@ private:<br>
NumTrampolines);<br>
}<br>
<br>
- std::error_code handleGetSymbolAddress() {<br>
- std::string SymbolName;<br>
- if (auto EC = handle<GetSymbolAddress>(Channel, readArgs(SymbolName)))<br>
- return EC;<br>
-<br>
- TargetAddress SymbolAddr = SymbolLookup(SymbolName);<br>
- DEBUG(dbgs() << " Symbol '" << SymbolName<br>
- << "' = " << format("0x%016x", SymbolAddr) << "\n");<br>
- return call<GetSymbolAddressResponse>(Channel, SymbolAddr);<br>
+ std::error_code handleGetSymbolAddress(const std::string &Name) {<br>
+ TargetAddress Addr = SymbolLookup(Name);<br>
+ DEBUG(dbgs() << " Symbol '" << Name << "' = " << format("0x%016x", Addr)<br>
+ << "\n");<br>
+ return call<GetSymbolAddressResponse>(Channel, Addr);<br>
}<br>
<br>
std::error_code handleGetRemoteInfo() {<br>
- if (auto EC = handle<GetRemoteInfo>(Channel, doNothing))<br>
- return EC;<br>
-<br>
std::string ProcessTriple = sys::getProcessTriple();<br>
uint32_t PointerSize = TargetT::PointerSize;<br>
uint32_t PageSize = sys::Process::getPageSize();<br>
@@ -389,16 +350,8 @@ private:<br>
IndirectStubSize);<br>
}<br>
<br>
- std::error_code handleReadMem() {<br>
- char *Src = nullptr;<br>
- uint64_t Size = 0;<br>
- if (std::error_code EC =<br>
- handle<ReadMem>(Channel, [&](TargetAddress RSrc, uint64_t RSize) {<br>
- Src = reinterpret_cast<char *>(static_cast<uintptr_t>(RSrc));<br>
- Size = RSize;<br>
- return std::error_code();<br>
- }))<br>
- return EC;<br>
+ std::error_code handleReadMem(TargetAddress RSrc, uint64_t Size) {<br>
+ char *Src = reinterpret_cast<char *>(static_cast<uintptr_t>(RSrc));<br>
<br>
DEBUG(dbgs() << " Reading " << Size << " bytes from "<br>
<< static_cast<void *>(Src) << "\n");<br>
@@ -412,62 +365,49 @@ private:<br>
return Channel.send();<br>
}<br>
<br>
- std::error_code handleReserveMem() {<br>
+ std::error_code handleReserveMem(ResourceIdMgr::ResourceId Id, uint64_t Size,<br>
+ uint32_t Align) {<br>
+ auto I = Allocators.find(Id);<br>
+ if (I == Allocators.end())<br>
+ return orcError(OrcErrorCode::RemoteAllocatorDoesNotExist);<br>
+ auto &Allocator = I->second;<br>
void *LocalAllocAddr = nullptr;<br>
-<br>
- if (std::error_code EC =<br>
- handle<ReserveMem>(Channel, [&](ResourceIdMgr::ResourceId Id,<br>
- uint64_t Size, uint32_t Align) {<br>
- auto I = Allocators.find(Id);<br>
- if (I == Allocators.end())<br>
- return orcError(OrcErrorCode::RemoteAllocatorDoesNotExist);<br>
- auto &Allocator = I->second;<br>
- auto EC2 = Allocator.allocate(LocalAllocAddr, Size, Align);<br>
- DEBUG(dbgs() << " Allocator " << Id << " reserved "<br>
- << LocalAllocAddr << " (" << Size<br>
- << " bytes, alignment " << Align << ")\n");<br>
- return EC2;<br>
- }))<br>
+ if (auto EC = Allocator.allocate(LocalAllocAddr, Size, Align))<br>
return EC;<br>
<br>
+ DEBUG(dbgs() << " Allocator " << Id << " reserved " << LocalAllocAddr<br>
+ << " (" << Size << " bytes, alignment " << Align << ")\n");<br>
+<br>
TargetAddress AllocAddr =<br>
static_cast<TargetAddress>(reinterpret_cast<uintptr_t>(LocalAllocAddr));<br>
<br>
return call<ReserveMemResponse>(Channel, AllocAddr);<br>
}<br>
<br>
- std::error_code handleSetProtections() {<br>
- return handle<ReserveMem>(Channel, [&](ResourceIdMgr::ResourceId Id,<br>
- TargetAddress Addr, uint32_t Flags) {<br>
- auto I = Allocators.find(Id);<br>
- if (I == Allocators.end())<br>
- return orcError(OrcErrorCode::RemoteAllocatorDoesNotExist);<br>
- auto &Allocator = I->second;<br>
- void *LocalAddr = reinterpret_cast<void *>(static_cast<uintptr_t>(Addr));<br>
- DEBUG(dbgs() << " Allocator " << Id << " set permissions on "<br>
- << LocalAddr << " to "<br>
- << (Flags & sys::Memory::MF_READ ? 'R' : '-')<br>
- << (Flags & sys::Memory::MF_WRITE ? 'W' : '-')<br>
- << (Flags & sys::Memory::MF_EXEC ? 'X' : '-') << "\n");<br>
- return Allocator.setProtections(LocalAddr, Flags);<br>
- });<br>
- }<br>
-<br>
- std::error_code handleWriteMem() {<br>
- return handle<WriteMem>(Channel, [&](TargetAddress RDst, uint64_t Size) {<br>
- char *Dst = reinterpret_cast<char *>(static_cast<uintptr_t>(RDst));<br>
- return Channel.readBytes(Dst, Size);<br>
- });<br>
- }<br>
-<br>
- std::error_code handleWritePtr() {<br>
- return handle<WritePtr>(<br>
- Channel, [&](TargetAddress Addr, TargetAddress PtrVal) {<br>
- uintptr_t *Ptr =<br>
- reinterpret_cast<uintptr_t *>(static_cast<uintptr_t>(Addr));<br>
- *Ptr = static_cast<uintptr_t>(PtrVal);<br>
- return std::error_code();<br>
- });<br>
+ std::error_code handleSetProtections(ResourceIdMgr::ResourceId Id,<br>
+ TargetAddress Addr, uint32_t Flags) {<br>
+ auto I = Allocators.find(Id);<br>
+ if (I == Allocators.end())<br>
+ return orcError(OrcErrorCode::RemoteAllocatorDoesNotExist);<br>
+ auto &Allocator = I->second;<br>
+ void *LocalAddr = reinterpret_cast<void *>(static_cast<uintptr_t>(Addr));<br>
+ DEBUG(dbgs() << " Allocator " << Id << " set permissions on " << LocalAddr<br>
+ << " to " << (Flags & sys::Memory::MF_READ ? 'R' : '-')<br>
+ << (Flags & sys::Memory::MF_WRITE ? 'W' : '-')<br>
+ << (Flags & sys::Memory::MF_EXEC ? 'X' : '-') << "\n");<br>
+ return Allocator.setProtections(LocalAddr, Flags);<br>
+ }<br>
+<br>
+ std::error_code handleWriteMem(TargetAddress RDst, uint64_t Size) {<br>
+ char *Dst = reinterpret_cast<char *>(static_cast<uintptr_t>(RDst));<br>
+ return Channel.readBytes(Dst, Size);<br>
+ }<br>
+<br>
+ std::error_code handleWritePtr(TargetAddress Addr, TargetAddress PtrVal) {<br>
+ uintptr_t *Ptr =<br>
+ reinterpret_cast<uintptr_t *>(static_cast<uintptr_t>(Addr));<br>
+ *Ptr = static_cast<uintptr_t>(PtrVal);<br>
+ return std::error_code();<br>
}<br>
<br>
ChannelT &Channel;<br>
<br>
Modified: llvm/trunk/include/llvm/ExecutionEngine/Orc/RPCUtils.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/Orc/RPCUtils.h?rev=257452&r1=257451&r2=257452&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/Orc/RPCUtils.h?rev=257452&r1=257451&r2=257452&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/ExecutionEngine/Orc/RPCUtils.h (original)<br>
+++ llvm/trunk/include/llvm/ExecutionEngine/Orc/RPCUtils.h Tue Jan 12 00:48:52 2016<br>
@@ -69,6 +69,20 @@ protected:<br>
}<br>
};<br>
<br>
+ template <typename ClassT, typename... ArgTs> class MemberFnWrapper {<br></blockquote><div><br></div><div>Might be able to use std::bind + std::mem_fn rather than writing your own wrapper</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+ public:<br>
+ typedef std::error_code (ClassT::*MethodT)(ArgTs...);<br>
+ MemberFnWrapper(ClassT &Instance, MethodT Method)<br>
+ : Instance(Instance), Method(Method) {}<br>
+ std::error_code operator()(ArgTs &... Args) {<br>
+ return (Instance.*Method)(Args...);<br>
+ }<br>
+<br>
+ private:<br>
+ ClassT &Instance;<br>
+ MethodT Method;<br>
+ };<br>
+<br>
template <typename... ArgTs> class ReadArgs {<br>
public:<br>
std::error_code operator()() { return std::error_code(); }<br>
@@ -193,6 +207,15 @@ public:<br>
return HandlerHelper<ChannelT, Proc>::handle(C, Handler);<br>
}<br>
<br>
+ /// Helper version of 'handle' for calling member functions.<br>
+ template <typename Proc, typename ClassT, typename... ArgTs><br>
+ static std::error_code<br>
+ handle(ChannelT &C, ClassT &Instance,<br>
+ std::error_code (ClassT::*HandlerMethod)(ArgTs...)) {<br>
+ return handle<Proc>(<br>
+ C, MemberFnWrapper<ClassT, ArgTs...>(Instance, HandlerMethod));<br>
+ }<br>
+<br>
/// Deserialize a ProcedureIdT from C and verify it matches the id for Proc.<br>
/// If the id does match, deserialize the arguments and call the handler<br>
/// (similarly to handle).<br>
@@ -208,6 +231,15 @@ public:<br>
return handle<Proc>(C, Handler);<br>
}<br>
<br>
+ /// Helper version of expect for calling member functions.<br>
+ template <typename Proc, typename ClassT, typename... ArgTs><br>
+ static std::error_code<br>
+ expect(ChannelT &C, ClassT &Instance,<br>
+ std::error_code (ClassT::*HandlerMethod)(ArgTs...)) {<br>
+ return expect<Proc>(<br>
+ C, MemberFnWrapper<ClassT, ArgTs...>(Instance, HandlerMethod));<br>
+ }<br>
+<br>
/// Helper for handling setter procedures - this method returns a functor that<br>
/// sets the variables referred to by Args... to values deserialized from the<br>
/// channel.<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div></div>