Robert Shearman : ole32: Reuse event handles used for COM calls.
Alexandre Julliard
julliard at wine.codeweavers.com
Mon Jun 19 03:35:22 CDT 2006
Module: wine
Branch: refs/heads/master
Commit: aa09031c78016cd8d0ff4108b6b132ba727a9b9e
URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=aa09031c78016cd8d0ff4108b6b132ba727a9b9e
Author: Robert Shearman <rob at 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;
More information about the wine-cvs
mailing list