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, &params->stub, &params->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, &params->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