From: Alistair Leslie-Hughes Subject: [PATCH] dpnet: IDirectPlay8ThreadPool is a singleton interface. Message-Id: Date: Fri, 17 Feb 2017 06:43:01 +0000 Signed-off-by: Alistair Leslie-Hughes --- dlls/dpnet/dpnet_main.c | 1 + dlls/dpnet/dpnet_private.h | 2 +- dlls/dpnet/tests/thread.c | 6 ++--- dlls/dpnet/threadpool.c | 61 +++++++++++++++++++++++++++++----------------- 4 files changed, 43 insertions(+), 27 deletions(-) diff --git a/dlls/dpnet/dpnet_main.c b/dlls/dpnet/dpnet_main.c index cc80ebc..ffa7aae 100644 --- a/dlls/dpnet/dpnet_main.c +++ b/dlls/dpnet/dpnet_main.c @@ -77,6 +77,7 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpvReserved) if (lpvReserved) break; if(winsock_loaded) WSACleanup(); + release_threadpool(); break; } return TRUE; diff --git a/dlls/dpnet/dpnet_private.h b/dlls/dpnet/dpnet_private.h index 7b6de4a..013bca7 100644 --- a/dlls/dpnet/dpnet_private.h +++ b/dlls/dpnet/dpnet_private.h @@ -121,7 +121,6 @@ struct IDirectPlay8LobbiedApplicationImpl struct IDirectPlay8ThreadPoolImpl { IDirectPlay8ThreadPool IDirectPlay8ThreadPool_iface; - LONG ref; PFNDPNMESSAGEHANDLER msghandler; DWORD flags; @@ -143,6 +142,7 @@ extern void init_dpn_sp_caps(DPN_SP_CAPS *dpnspcaps) DECLSPEC_HIDDEN; extern void init_winsock(void) DECLSPEC_HIDDEN; extern HRESULT enum_services_providers(const GUID * const service, DPN_SERVICE_PROVIDER_INFO * const info_buffer, DWORD * const buf_size, DWORD * const returned) DECLSPEC_HIDDEN; +extern void release_threadpool(void) DECLSPEC_HIDDEN; /* used for generic dumping (copied from ddraw) */ typedef struct { diff --git a/dlls/dpnet/tests/thread.c b/dlls/dpnet/tests/thread.c index 7129739..80a7ce5 100644 --- a/dlls/dpnet/tests/thread.c +++ b/dlls/dpnet/tests/thread.c @@ -70,7 +70,7 @@ static void create_threadpool(void) ok(hr == S_OK, "got 0x%08x\n", hr); hr = IDirectPlay8ThreadPool_Initialize(pool2, NULL, &DirectPlayThreadHandler, 0); - todo_wine ok(hr == DPNERR_ALREADYINITIALIZED, "got 0x%08x\n", hr); + ok(hr == DPNERR_ALREADYINITIALIZED, "got 0x%08x\n", hr); hr = IDirectPlay8ThreadPool_GetThreadCount(pool1, -1, &threadcnt, 0); ok(hr == S_OK, "got 0x%08x\n", hr); @@ -219,13 +219,13 @@ static void test_singleton(void) hr = CoCreateInstance( &CLSID_DirectPlay8ThreadPool, NULL, CLSCTX_ALL, &IID_IDirectPlay8ThreadPool, (void**)&pool2); ok(hr == S_OK, "got 0x%08x\n", hr); - ok(pool1 != pool2, "same pointer returned.\n"); + todo_wine ok(pool1 != pool2, "same pointer returned.\n"); hr = IDirectPlay8ThreadPool_Initialize(pool1, NULL, &DirectPlayThreadHandler, 0); ok(hr == S_OK, "got 0x%08x\n", hr); hr = IDirectPlay8ThreadPool_Initialize(pool2, NULL, &DirectPlayThreadHandler, 0); - todo_wine ok(hr == DPNERR_ALREADYINITIALIZED, "got 0x%08x\n", hr); + ok(hr == DPNERR_ALREADYINITIALIZED, "got 0x%08x\n", hr); hr = IDirectPlay8ThreadPool_Close(pool1, 0); ok(hr == S_OK, "got 0x%08x\n", hr); diff --git a/dlls/dpnet/threadpool.c b/dlls/dpnet/threadpool.c index 37a05e2..c6b59f4 100644 --- a/dlls/dpnet/threadpool.c +++ b/dlls/dpnet/threadpool.c @@ -36,6 +36,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(dpnet); +static IDirectPlay8ThreadPool *threadpool = NULL; + static inline IDirectPlay8ThreadPoolImpl *impl_from_IDirectPlay8ThreadPool(IDirectPlay8ThreadPool *iface) { return CONTAINING_RECORD(iface, IDirectPlay8ThreadPoolImpl, IDirectPlay8ThreadPool_iface); @@ -61,21 +63,12 @@ static HRESULT WINAPI IDirectPlay8ThreadPoolImpl_QueryInterface(IDirectPlay8Thre static ULONG WINAPI IDirectPlay8ThreadPoolImpl_AddRef(IDirectPlay8ThreadPool *iface) { - IDirectPlay8ThreadPoolImpl* This = impl_from_IDirectPlay8ThreadPool(iface); - ULONG RefCount = InterlockedIncrement(&This->ref); - - return RefCount; + return 2; } static ULONG WINAPI IDirectPlay8ThreadPoolImpl_Release(IDirectPlay8ThreadPool *iface) { - IDirectPlay8ThreadPoolImpl* This = impl_from_IDirectPlay8ThreadPool(iface); - ULONG RefCount = InterlockedDecrement(&This->ref); - - if(!RefCount) - HeapFree(GetProcessHeap(), 0, This); - - return RefCount; + return 1; } /* IDirectPlay8ThreadPool interface follows */ @@ -151,22 +144,44 @@ static const IDirectPlay8ThreadPoolVtbl DirectPlay8ThreadPool_Vtbl = IDirectPlay8ThreadPoolImpl_DoWork }; -HRESULT DPNET_CreateDirectPlay8ThreadPool(LPCLASSFACTORY iface, LPUNKNOWN punkOuter, REFIID riid, LPVOID *ppobj) +static IDirectPlay8ThreadPool *get_threadpool(void) { - IDirectPlay8ThreadPoolImpl* Client; + if (!threadpool) + { + IDirectPlay8ThreadPoolImpl *obj; - Client = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectPlay8ThreadPoolImpl)); + obj = heap_alloc(sizeof(IDirectPlay8ThreadPoolImpl)); + if (!obj) + return NULL; - if(Client == NULL) - { - *ppobj = NULL; - WARN("Not enough memory\n"); - return E_OUTOFMEMORY; + obj->IDirectPlay8ThreadPool_iface.lpVtbl = &DirectPlay8ThreadPool_Vtbl; + obj->msghandler = NULL; + obj->flags = 0; + obj->usercontext = NULL; + + if (InterlockedCompareExchangePointer((void**)&threadpool, &obj->IDirectPlay8ThreadPool_iface, NULL)) + HeapFree(GetProcessHeap(), 0, obj); + else + TRACE("Created the threadpool at %p\n", obj); } - Client->IDirectPlay8ThreadPool_iface.lpVtbl = &DirectPlay8ThreadPool_Vtbl; - Client->ref = 0; + return threadpool; +} - return IDirectPlay8ThreadPoolImpl_QueryInterface(&Client->IDirectPlay8ThreadPool_iface, riid, - ppobj); +void release_threadpool(void) +{ + IDirectPlay8ThreadPoolImpl *pool; + + if (!threadpool) + return; + + pool = impl_from_IDirectPlay8ThreadPool(threadpool); + + heap_free(pool); +} + +HRESULT DPNET_CreateDirectPlay8ThreadPool(IClassFactory *iface, LPUNKNOWN punkOuter, REFIID riid, void **obj) +{ + IDirectPlay8ThreadPool *pool = get_threadpool(); + return IDirectPlay8ThreadPool_QueryInterface(pool, riid, obj); } -- 1.9.1