Module: wine Branch: refs/heads/master Commit: aa09031c78016cd8d0ff4108b6b132ba727a9b9e URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=aa09031c78016cd8d0ff4108...
Author: Robert Shearman rob@codeweavers.com Date: Sat Jun 17 12:31:44 2006 +0100
ole32: Reuse event handles used for COM calls.
This reduces the number of server calls during a COM call by half.
---
dlls/ole32/rpc.c | 25 +++++++++++++++++++++++-- 1 files changed, 23 insertions(+), 2 deletions(-)
diff --git a/dlls/ole32/rpc.c b/dlls/ole32/rpc.c index e30989d..cf49698 100644 --- a/dlls/ole32/rpc.c +++ b/dlls/ole32/rpc.c @@ -100,6 +100,7 @@ typedef struct OXID oxid; /* apartment in which the channel is valid */ DWORD dest_context; /* returned from GetDestCtx */ LPVOID dest_context_data; /* returned from GetDestCtx */ + HANDLE event; /* cached event handle */ } ClientRpcChannelBuffer;
struct dispatch_params @@ -152,6 +153,7 @@ static ULONG WINAPI ClientRpcChannelBuff if (ref) return ref;
+ if (This->event) CloseHandle(This->event); RpcBindingFree(&This->bind); HeapFree(GetProcessHeap(), 0, This); return 0; @@ -207,6 +209,24 @@ static HRESULT WINAPI ServerRpcChannelBu return E_NOTIMPL; }
+static HANDLE ClientRpcChannelBuffer_GetEventHandle(ClientRpcChannelBuffer *This) +{ + HANDLE event = InterlockedExchangePointer(&This->event, NULL); + + /* Note: must be auto-reset event so we can reuse it without a call + * to ResetEvent */ + if (!event) event = CreateEventW(NULL, FALSE, FALSE, NULL); + + return event; +} + +static void ClientRpcChannelBuffer_ReleaseEventHandle(ClientRpcChannelBuffer *This, HANDLE event) +{ + if (InterlockedCompareExchangePointer(&This->event, event, NULL)) + /* already a handle cached in This */ + CloseHandle(event); +} + /* this thread runs an outgoing RPC */ static DWORD WINAPI rpc_sendreceive_thread(LPVOID param) { @@ -271,7 +291,7 @@ static HRESULT WINAPI ClientRpcChannelBu
RpcBindingInqObject(msg->Handle, &ipid); hr = ipid_get_dispatch_params(&ipid, &apt, ¶ms->stub, ¶ms->chan); - params->handle = CreateEventW(NULL, FALSE, FALSE, NULL); + params->handle = ClientRpcChannelBuffer_GetEventHandle(This); if ((hr == S_OK) && !apt->multi_threaded) { TRACE("Calling apartment thread 0x%08lx...\n", apt->tid); @@ -315,7 +335,7 @@ static HRESULT WINAPI ClientRpcChannelBu if (WaitForSingleObject(params->handle, 0)) hr = CoWaitForMultipleHandles(0, INFINITE, 1, ¶ms->handle, &index); } - CloseHandle(params->handle); + ClientRpcChannelBuffer_ReleaseEventHandle(This, params->handle);
if (hr == S_OK) hr = params->hr;
@@ -478,6 +498,7 @@ HRESULT RPC_CreateClientChannel(const OX apartment_getoxid(COM_CurrentApt(), &This->oxid); This->dest_context = dest_context; This->dest_context_data = dest_context_data; + This->event = NULL;
*chan = (IRpcChannelBuffer*)This;