typedef struct _TP_POOL TP_POOL, *PTP_POOL;
-typedef enum _TP_CALLBACK_PRIORITY
-{
- TP_CALLBACK_PRIORITY_HIGH,
- TP_CALLBACK_PRIORITY_NORMAL,
- TP_CALLBACK_PRIORITY_LOW,
- TP_CALLBACK_PRIORITY_INVALID,
- TP_CALLBACK_PRIORITY_COUNT = TP_CALLBACK_PRIORITY_INVALID
-} TP_CALLBACK_PRIORITY;
-
typedef struct _TP_POOL_STACK_INFORMATION
{
SIZE_T StackReserve;
} u;
} TP_CALLBACK_ENVIRON_V1;
-#endif
-
-/* Non-Windows and pre Windows 7 */
-#if ((!defined(_WIN32)) || (defined(_WIN32) && (_WIN32_WINNT < 0x0601)))
-
-typedef struct _TP_CALLBACK_ENVIRON_V3
-{
- TP_VERSION Version;
- PTP_POOL Pool;
- PTP_CLEANUP_GROUP CleanupGroup;
- PTP_CLEANUP_GROUP_CANCEL_CALLBACK CleanupGroupCancelCallback;
- PVOID RaceDll;
- struct _ACTIVATION_CONTEXT *ActivationContext;
- PTP_SIMPLE_CALLBACK FinalizationCallback;
-
- union
- {
- DWORD Flags;
-
- struct
- {
- DWORD LongFunction:1;
- DWORD Persistent:1;
- DWORD Private:30;
- } s;
- } u;
-
- TP_CALLBACK_PRIORITY CallbackPriority;
- DWORD Size;
-} TP_CALLBACK_ENVIRON_V3;
-
-//typedef TP_CALLBACK_ENVIRON_V3 TP_CALLBACK_ENVIRON, *PTP_CALLBACK_ENVIRON;
+typedef TP_CALLBACK_ENVIRON_V1 TP_CALLBACK_ENVIRON, *PTP_CALLBACK_ENVIRON;
-#endif
+#endif /* _WIN32 not defined */
typedef struct _TP_WORK TP_WORK, *PTP_WORK;
typedef struct _TP_TIMER TP_TIMER, *PTP_TIMER;
typedef struct _TP_IO TP_IO, *PTP_IO;
-#if !defined(_WIN32) || (defined(_WIN32) && (_WIN32_WINNT < 0x0601))
-typedef TP_CALLBACK_ENVIRON_V1 TP_CALLBACK_ENVIRON, *PTP_CALLBACK_ENVIRON;
-#endif
#ifndef _WIN32
#endif
-#if (!defined(_WIN32) || ((defined(_WIN32) && (_WIN32_WINNT < 0x0601))))
+#if (!defined(_WIN32) || ((defined(_WIN32) && (_WIN32_WINNT < 0x0600))))
#define WINPR_THREAD_POOL 1
#endif
/* Callback Environment */
-WINPR_API VOID InitializeThreadpoolEnvironment(PTP_CALLBACK_ENVIRON pcbe);
-WINPR_API VOID DestroyThreadpoolEnvironment(PTP_CALLBACK_ENVIRON pcbe);
-WINPR_API VOID SetThreadpoolCallbackPool(PTP_CALLBACK_ENVIRON pcbe, PTP_POOL ptpp);
-WINPR_API VOID SetThreadpoolCallbackCleanupGroup(PTP_CALLBACK_ENVIRON pcbe,
- PTP_CLEANUP_GROUP ptpcg, PTP_CLEANUP_GROUP_CANCEL_CALLBACK pfng);
-WINPR_API VOID SetThreadpoolCallbackRunsLong(PTP_CALLBACK_ENVIRON pcbe);
-WINPR_API VOID SetThreadpoolCallbackLibrary(PTP_CALLBACK_ENVIRON pcbe, PVOID mod);
-WINPR_API VOID SetThreadpoolCallbackPriority(PTP_CALLBACK_ENVIRON pcbe, TP_CALLBACK_PRIORITY Priority);
+static INLINE VOID InitializeThreadpoolEnvironment(PTP_CALLBACK_ENVIRON pcbe)
+{
+ pcbe->Version = 1;
+ pcbe->Pool = NULL;
+ pcbe->CleanupGroup = NULL;
+ pcbe->CleanupGroupCancelCallback = NULL;
+ pcbe->RaceDll = NULL;
+ pcbe->ActivationContext = NULL;
+ pcbe->FinalizationCallback = NULL;
+ pcbe->u.Flags = 0;
+}
+
+static INLINE VOID DestroyThreadpoolEnvironment(PTP_CALLBACK_ENVIRON pcbe)
+{
+ /* no actions, this may change in a future release. */
+}
+
+static INLINE VOID SetThreadpoolCallbackPool(PTP_CALLBACK_ENVIRON pcbe, PTP_POOL ptpp)
+{
+ pcbe->Pool = ptpp;
+}
+
+static INLINE VOID SetThreadpoolCallbackCleanupGroup(PTP_CALLBACK_ENVIRON pcbe, PTP_CLEANUP_GROUP ptpcg, PTP_CLEANUP_GROUP_CANCEL_CALLBACK pfng)
+{
+ pcbe->CleanupGroup = ptpcg;
+ pcbe->CleanupGroupCancelCallback = pfng;
+}
+
+static INLINE VOID SetThreadpoolCallbackRunsLong(PTP_CALLBACK_ENVIRON pcbe)
+{
+ pcbe->u.s.LongFunction = 1;
+}
+
+static INLINE VOID SetThreadpoolCallbackLibrary(PTP_CALLBACK_ENVIRON pcbe, PVOID mod)
+{
+ pcbe->RaceDll = mod;
+}
+
/* Callback */
#endif
-#if (defined(_WIN32) && defined(_SYNCHAPI_H_) && (_WIN32_WINNT < 0x0600))
-#define WINPR_INITIALIZE_CRITICAL_SECTION_EX 1
-#elif (defined(_WIN32) && (_WIN32_WINNT < 0x0403))
-#define WINPR_INITIALIZE_CRITICAL_SECTION_EX 1
-#endif
-
-#ifdef WINPR_INITIALIZE_CRITICAL_SECTION_EX
-
-WINPR_API BOOL InitializeCriticalSectionEx(LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount, DWORD Flags);
-
+#if (defined(_WIN32) && (_WIN32_WINNT < 0x0600))
+#define InitializeCriticalSectionEx(A,B,C) InitializeCriticalSectionAndSpinCount(A,B)
#endif
#ifndef _RTL_RUN_ONCE_DEF
return -1;
/* Check for unsupported flags. */
- if (flags & ~(_S_IREAD | _S_IWRITE) != 0)
+ if (flags & ~(_S_IREAD | _S_IWRITE))
WLog_WARN(TAG, "Unsupported file mode %d for _wchmod", flags);
rc = _wchmod(wfl, flags);
cleanup_group.c
pool.c
pool.h
- callback_environment.c
callback.c
callback_cleanup.c)
#include <winpr/pool.h>
#include <winpr/library.h>
-#ifdef _WIN32
-
-static BOOL module_initialized = FALSE;
-static BOOL module_available = FALSE;
-static HMODULE kernel32_module = NULL;
+#ifdef WINPR_THREAD_POOL
+#ifdef _WIN32
+static INIT_ONCE init_once_module = INIT_ONCE_STATIC_INIT;
static BOOL (WINAPI * pCallbackMayRunLong)(PTP_CALLBACK_INSTANCE pci);
-static void module_init()
+static BOOL CALLBACK init_module(PINIT_ONCE once, PVOID param, PVOID *context)
{
- if (module_initialized)
- return;
-
- kernel32_module = LoadLibraryA("kernel32.dll");
- module_initialized = TRUE;
-
- if (!kernel32_module)
- return;
-
- module_available = TRUE;
-
- pCallbackMayRunLong = (void*) GetProcAddress(kernel32_module, "CallbackMayRunLong");
+ HMODULE kernel32 = LoadLibraryA("kernel32.dll");
+ if (kernel32)
+ {
+ pCallbackMayRunLong = (void*)GetProcAddress(kernel32, "CallbackMayRunLong");
+ }
+ return TRUE;
}
-
#endif
-#ifdef WINPR_THREAD_POOL
-
BOOL CallbackMayRunLong(PTP_CALLBACK_INSTANCE pci)
{
#ifdef _WIN32
- module_init();
-
+ InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL);
if (pCallbackMayRunLong)
return pCallbackMayRunLong(pci);
-#else
#endif
+ /* No default implementation */
return FALSE;
}
-#endif
+#endif /* WINPR_THREAD_POOL defined */
#include "pool.h"
-#ifdef _WIN32
-
-static BOOL module_initialized = FALSE;
-static BOOL module_available = FALSE;
-static HMODULE kernel32_module = NULL;
+#ifdef WINPR_THREAD_POOL
+#ifdef _WIN32
+static INIT_ONCE init_once_module = INIT_ONCE_STATIC_INIT;
static VOID (WINAPI * pSetEventWhenCallbackReturns)(PTP_CALLBACK_INSTANCE pci, HANDLE evt);
static VOID (WINAPI * pReleaseSemaphoreWhenCallbackReturns)(PTP_CALLBACK_INSTANCE pci, HANDLE sem, DWORD crel);
static VOID (WINAPI * pReleaseMutexWhenCallbackReturns)(PTP_CALLBACK_INSTANCE pci, HANDLE mut);
static VOID (WINAPI * pFreeLibraryWhenCallbackReturns)(PTP_CALLBACK_INSTANCE pci, HMODULE mod);
static VOID (WINAPI * pDisassociateCurrentThreadFromCallback)(PTP_CALLBACK_INSTANCE pci);
-static void module_init()
+static BOOL CALLBACK init_module(PINIT_ONCE once, PVOID param, PVOID *context)
{
- if (module_initialized)
- return;
-
- kernel32_module = LoadLibraryA("kernel32.dll");
- module_initialized = TRUE;
-
- if (!kernel32_module)
- return;
-
- module_available = TRUE;
-
- pSetEventWhenCallbackReturns = (void*) GetProcAddress(kernel32_module, "SetEventWhenCallbackReturns");
- pReleaseSemaphoreWhenCallbackReturns = (void*) GetProcAddress(kernel32_module, "ReleaseSemaphoreWhenCallbackReturns");
- pReleaseMutexWhenCallbackReturns = (void*) GetProcAddress(kernel32_module, "ReleaseMutexWhenCallbackReturns");
- pLeaveCriticalSectionWhenCallbackReturns = (void*) GetProcAddress(kernel32_module, "LeaveCriticalSectionWhenCallbackReturns");
- pFreeLibraryWhenCallbackReturns = (void*) GetProcAddress(kernel32_module, "FreeLibraryWhenCallbackReturns");
- pDisassociateCurrentThreadFromCallback = (void*) GetProcAddress(kernel32_module, "DisassociateCurrentThreadFromCallback");
+ HMODULE kernel32 = LoadLibraryA("kernel32.dll");
+ if (kernel32)
+ {
+ pSetEventWhenCallbackReturns = (void*)GetProcAddress(kernel32, "SetEventWhenCallbackReturns");
+ pReleaseSemaphoreWhenCallbackReturns = (void*)GetProcAddress(kernel32, "ReleaseSemaphoreWhenCallbackReturns");
+ pReleaseMutexWhenCallbackReturns = (void*)GetProcAddress(kernel32, "ReleaseMutexWhenCallbackReturns");
+ pLeaveCriticalSectionWhenCallbackReturns = (void*)GetProcAddress(kernel32, "LeaveCriticalSectionWhenCallbackReturns");
+ pFreeLibraryWhenCallbackReturns = (void*)GetProcAddress(kernel32, "FreeLibraryWhenCallbackReturns");
+ pDisassociateCurrentThreadFromCallback = (void*)GetProcAddress(kernel32, "DisassociateCurrentThreadFromCallback");
+ }
+ return TRUE;
}
-
#endif
-#ifdef WINPR_THREAD_POOL
-
VOID SetEventWhenCallbackReturns(PTP_CALLBACK_INSTANCE pci, HANDLE evt)
{
#ifdef _WIN32
- module_init();
-
+ InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL);
if (pSetEventWhenCallbackReturns)
+ {
pSetEventWhenCallbackReturns(pci, evt);
-#else
+ return;
+ }
#endif
+ /* No default implementation */
}
VOID ReleaseSemaphoreWhenCallbackReturns(PTP_CALLBACK_INSTANCE pci, HANDLE sem, DWORD crel)
{
#ifdef _WIN32
- module_init();
-
+ InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL);
if (pReleaseSemaphoreWhenCallbackReturns)
+ {
pReleaseSemaphoreWhenCallbackReturns(pci, sem, crel);
-#else
+ return;
+ }
#endif
+ /* No default implementation */
}
VOID ReleaseMutexWhenCallbackReturns(PTP_CALLBACK_INSTANCE pci, HANDLE mut)
{
#ifdef _WIN32
- module_init();
-
+ InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL);
if (pReleaseMutexWhenCallbackReturns)
+ {
pReleaseMutexWhenCallbackReturns(pci, mut);
-#else
+ return;
+ }
#endif
+ /* No default implementation */
}
VOID LeaveCriticalSectionWhenCallbackReturns(PTP_CALLBACK_INSTANCE pci, PCRITICAL_SECTION pcs)
{
#ifdef _WIN32
- module_init();
-
+ InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL);
if (pLeaveCriticalSectionWhenCallbackReturns)
+ {
pLeaveCriticalSectionWhenCallbackReturns(pci, pcs);
-#else
+ }
#endif
+ /* No default implementation */
}
VOID FreeLibraryWhenCallbackReturns(PTP_CALLBACK_INSTANCE pci, HMODULE mod)
{
#ifdef _WIN32
- module_init();
-
+ InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL);
if (pFreeLibraryWhenCallbackReturns)
+ {
pFreeLibraryWhenCallbackReturns(pci, mod);
-#else
+ return;
+ }
#endif
+ /* No default implementation */
}
VOID DisassociateCurrentThreadFromCallback(PTP_CALLBACK_INSTANCE pci)
{
#ifdef _WIN32
- module_init();
-
+ InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL);
if (pDisassociateCurrentThreadFromCallback)
+ {
pDisassociateCurrentThreadFromCallback(pci);
-#else
+ return;
+ }
#endif
+ /* No default implementation */
}
-#endif
+#endif /* WINPR_THREAD_POOL defined */
+++ /dev/null
-/**
- * WinPR: Windows Portable Runtime
- * Thread Pool API (Callback Environment)
- *
- * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <winpr/crt.h>
-#include <winpr/pool.h>
-#include <winpr/library.h>
-
-#include "pool.h"
-
-#ifdef WINPR_THREAD_POOL
-
-VOID InitializeCallbackEnvironment_V1(TP_CALLBACK_ENVIRON_V1* pcbe)
-{
- pcbe->Version = 1;
-
- pcbe->Pool = NULL;
- pcbe->CleanupGroup = NULL;
- pcbe->CleanupGroupCancelCallback = NULL;
- pcbe->RaceDll = NULL;
- pcbe->ActivationContext = NULL;
- pcbe->FinalizationCallback = NULL;
- pcbe->u.Flags = 0;
-}
-
-VOID InitializeCallbackEnvironment_V3(TP_CALLBACK_ENVIRON_V3* pcbe)
-{
- pcbe->Version = 3;
-
- pcbe->Pool = NULL;
- pcbe->CleanupGroup = NULL;
- pcbe->CleanupGroupCancelCallback = NULL;
- pcbe->RaceDll = NULL;
- pcbe->ActivationContext = NULL;
- pcbe->FinalizationCallback = NULL;
- pcbe->u.Flags = 0;
-
- pcbe->CallbackPriority = TP_CALLBACK_PRIORITY_NORMAL;
- pcbe->Size = sizeof(TP_CALLBACK_ENVIRON);
-}
-
-#endif
-
-#ifdef _WIN32
-
-static BOOL module_initialized = FALSE;
-static BOOL module_available = FALSE;
-static HMODULE kernel32_module = NULL;
-
-static VOID (WINAPI * pDestroyThreadpoolEnvironment)(PTP_CALLBACK_ENVIRON pcbe);
-static VOID (WINAPI * pSetThreadpoolCallbackPool)(PTP_CALLBACK_ENVIRON pcbe, PTP_POOL ptpp);
-static VOID (WINAPI * pSetThreadpoolCallbackCleanupGroup)(PTP_CALLBACK_ENVIRON pcbe, PTP_CLEANUP_GROUP ptpcg, PTP_CLEANUP_GROUP_CANCEL_CALLBACK pfng);
-static VOID (WINAPI * pSetThreadpoolCallbackRunsLong)(PTP_CALLBACK_ENVIRON pcbe);
-static VOID (WINAPI * pSetThreadpoolCallbackLibrary)(PTP_CALLBACK_ENVIRON pcbe, PVOID mod);
-static VOID (WINAPI * pSetThreadpoolCallbackPriority)(PTP_CALLBACK_ENVIRON pcbe, TP_CALLBACK_PRIORITY Priority);
-
-static void module_init()
-{
- if (module_initialized)
- return;
-
- kernel32_module = LoadLibraryA("kernel32.dll");
- module_initialized = TRUE;
-
- if (!kernel32_module)
- return;
-
- module_available = TRUE;
-
- /* InitializeThreadpoolEnvironment is an inline function */
- pDestroyThreadpoolEnvironment = (void*) GetProcAddress(kernel32_module, "DestroyThreadpoolEnvironment");
- pSetThreadpoolCallbackPool = (void*) GetProcAddress(kernel32_module, "SetThreadpoolCallbackPool");
- pSetThreadpoolCallbackCleanupGroup = (void*) GetProcAddress(kernel32_module, "SetThreadpoolCallbackCleanupGroup");
- pSetThreadpoolCallbackRunsLong = (void*) GetProcAddress(kernel32_module, "SetThreadpoolCallbackRunsLong");
- pSetThreadpoolCallbackRunsLong = (void*) GetProcAddress(kernel32_module, "SetThreadpoolCallbackRunsLong");
- pSetThreadpoolCallbackLibrary = (void*) GetProcAddress(kernel32_module, "SetThreadpoolCallbackLibrary");
- pSetThreadpoolCallbackPriority = (void*) GetProcAddress(kernel32_module, "SetThreadpoolCallbackPriority");
-}
-
-#else
-
-static TP_CALLBACK_ENVIRON DEFAULT_CALLBACK_ENVIRONMENT =
-{
- 1, /* Version */
- NULL, /* Pool */
- NULL, /* CleanupGroup */
- NULL, /* CleanupGroupCancelCallback */
- NULL, /* RaceDll */
- NULL, /* ActivationContext */
- NULL, /* FinalizationCallback */
- { 0 } /* Flags */
-};
-
-PTP_CALLBACK_ENVIRON GetDefaultThreadpoolEnvironment()
-{
- PTP_CALLBACK_ENVIRON environment = &DEFAULT_CALLBACK_ENVIRONMENT;
-
- environment->Pool = GetDefaultThreadpool();
-
- return environment;
-}
-
-#endif
-
-#ifdef WINPR_THREAD_POOL
-
-VOID InitializeThreadpoolEnvironment(PTP_CALLBACK_ENVIRON pcbe)
-{
- if (pcbe->Version == 3)
- InitializeCallbackEnvironment_V3((TP_CALLBACK_ENVIRON_V3*) pcbe);
- else
- InitializeCallbackEnvironment_V1(pcbe);
-}
-
-VOID DestroyThreadpoolEnvironment(PTP_CALLBACK_ENVIRON pcbe)
-{
-#ifdef _WIN32
- module_init();
-
- if (pDestroyThreadpoolEnvironment)
- pDestroyThreadpoolEnvironment(pcbe);
-#else
-#endif
-}
-
-VOID SetThreadpoolCallbackPool(PTP_CALLBACK_ENVIRON pcbe, PTP_POOL ptpp)
-{
-#ifdef _WIN32
- module_init();
-
- if (pSetThreadpoolCallbackPool)
- pSetThreadpoolCallbackPool(pcbe, ptpp);
-#else
- pcbe->Pool = ptpp;
-#endif
-}
-
-VOID SetThreadpoolCallbackCleanupGroup(PTP_CALLBACK_ENVIRON pcbe, PTP_CLEANUP_GROUP ptpcg, PTP_CLEANUP_GROUP_CANCEL_CALLBACK pfng)
-{
-#ifdef _WIN32
- module_init();
-
- if (pSetThreadpoolCallbackCleanupGroup)
- pSetThreadpoolCallbackCleanupGroup(pcbe, ptpcg, pfng);
-#else
- pcbe->CleanupGroup = ptpcg;
- pcbe->CleanupGroupCancelCallback = pfng;
-#endif
-}
-
-VOID SetThreadpoolCallbackRunsLong(PTP_CALLBACK_ENVIRON pcbe)
-{
-#ifdef _WIN32
- module_init();
-
- if (pSetThreadpoolCallbackRunsLong)
- pSetThreadpoolCallbackRunsLong(pcbe);
-#else
- pcbe->u.s.LongFunction = TRUE;
-#endif
-}
-
-VOID SetThreadpoolCallbackLibrary(PTP_CALLBACK_ENVIRON pcbe, PVOID mod)
-{
-#ifdef _WIN32
- module_init();
-
- if (pSetThreadpoolCallbackLibrary)
- pSetThreadpoolCallbackLibrary(pcbe, mod);
-#else
-#endif
-}
-
-VOID SetThreadpoolCallbackPriority(PTP_CALLBACK_ENVIRON pcbe, TP_CALLBACK_PRIORITY Priority)
-{
-#ifdef _WIN32
- module_init();
-
- if (pSetThreadpoolCallbackPriority)
- pSetThreadpoolCallbackPriority(pcbe, Priority);
-#else
-#endif
-}
-
-#endif
#include "pool.h"
-#ifdef _WIN32
-
-static BOOL module_initialized = FALSE;
-static BOOL module_available = FALSE;
-static HMODULE kernel32_module = NULL;
+#ifdef WINPR_THREAD_POOL
+#ifdef _WIN32
+static INIT_ONCE init_once_module = INIT_ONCE_STATIC_INIT;
static PTP_CLEANUP_GROUP (WINAPI * pCreateThreadpoolCleanupGroup)();
static VOID (WINAPI * pCloseThreadpoolCleanupGroupMembers)(PTP_CLEANUP_GROUP ptpcg, BOOL fCancelPendingCallbacks, PVOID pvCleanupContext);
static VOID (WINAPI * pCloseThreadpoolCleanupGroup)(PTP_CLEANUP_GROUP ptpcg);
-static void module_init()
+static BOOL CALLBACK init_module(PINIT_ONCE once, PVOID param, PVOID *context)
{
- if (module_initialized)
- return;
-
- kernel32_module = LoadLibraryA("kernel32.dll");
- module_initialized = TRUE;
-
- if (!kernel32_module)
- return;
-
- module_available = TRUE;
-
- pCreateThreadpoolCleanupGroup = (void*) GetProcAddress(kernel32_module, "CreateThreadpoolCleanupGroup");
- pCloseThreadpoolCleanupGroupMembers = (void*) GetProcAddress(kernel32_module, "CloseThreadpoolCleanupGroupMembers");
- pCloseThreadpoolCleanupGroup = (void*) GetProcAddress(kernel32_module, "CloseThreadpoolCleanupGroup");
+ HMODULE kernel32 = LoadLibraryA("kernel32.dll");
+ if (kernel32)
+ {
+ pCreateThreadpoolCleanupGroup = (void*)GetProcAddress(kernel32, "CreateThreadpoolCleanupGroup");
+ pCloseThreadpoolCleanupGroupMembers = (void*)GetProcAddress(kernel32, "CloseThreadpoolCleanupGroupMembers");
+ pCloseThreadpoolCleanupGroup = (void*)GetProcAddress(kernel32, "CloseThreadpoolCleanupGroup");
+ }
+ return TRUE;
}
-
#endif
-#if WINPR_THREAD_POOL
-
PTP_CLEANUP_GROUP CreateThreadpoolCleanupGroup()
{
PTP_CLEANUP_GROUP cleanupGroup = NULL;
#ifdef _WIN32
- module_init();
-
+ InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL);
if (pCreateThreadpoolCleanupGroup)
return pCreateThreadpoolCleanupGroup();
-#else
- cleanupGroup = (PTP_CLEANUP_GROUP) malloc(sizeof(TP_CLEANUP_GROUP));
#endif
+ cleanupGroup = (PTP_CLEANUP_GROUP) malloc(sizeof(TP_CLEANUP_GROUP));
return cleanupGroup;
}
VOID CloseThreadpoolCleanupGroupMembers(PTP_CLEANUP_GROUP ptpcg, BOOL fCancelPendingCallbacks, PVOID pvCleanupContext)
{
#ifdef _WIN32
- module_init();
-
+ InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL);
if (pCloseThreadpoolCleanupGroupMembers)
+ {
pCloseThreadpoolCleanupGroupMembers(ptpcg, fCancelPendingCallbacks, pvCleanupContext);
-#else
-
+ return;
+ }
#endif
+ /* No default implementation */
}
VOID CloseThreadpoolCleanupGroup(PTP_CLEANUP_GROUP ptpcg)
{
#ifdef _WIN32
- module_init();
-
+ InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL);
if (pCloseThreadpoolCleanupGroup)
+ {
pCloseThreadpoolCleanupGroup(ptpcg);
-#else
- free(ptpcg);
+ return;
+ }
#endif
+ free(ptpcg);
}
-#endif
+#endif /* WINPR_THREAD_POOL defined */
#include "pool.h"
-#ifdef _WIN32
-
-static BOOL module_initialized = FALSE;
-static BOOL module_available = FALSE;
-static HMODULE kernel32_module = NULL;
+#ifdef WINPR_THREAD_POOL
+#ifdef _WIN32
+static INIT_ONCE init_once_module = INIT_ONCE_STATIC_INIT;
static PTP_POOL (WINAPI * pCreateThreadpool)(PVOID reserved);
static VOID (WINAPI * pCloseThreadpool)(PTP_POOL ptpp);
static BOOL (WINAPI * pSetThreadpoolThreadMinimum)(PTP_POOL ptpp, DWORD cthrdMic);
static VOID (WINAPI * pSetThreadpoolThreadMaximum)(PTP_POOL ptpp, DWORD cthrdMost);
-static void module_init()
+static BOOL CALLBACK init_module(PINIT_ONCE once, PVOID param, PVOID *context)
{
- if (module_initialized)
- return;
-
- kernel32_module = LoadLibraryA("kernel32.dll");
- module_initialized = TRUE;
-
- if (!kernel32_module)
- return;
-
- module_available = TRUE;
-
- pCreateThreadpool = (void*) GetProcAddress(kernel32_module, "CreateThreadpool");
- pCloseThreadpool = (void*) GetProcAddress(kernel32_module, "CloseThreadpool");
- pSetThreadpoolThreadMinimum = (void*) GetProcAddress(kernel32_module, "SetThreadpoolThreadMinimum");
- pSetThreadpoolThreadMaximum = (void*) GetProcAddress(kernel32_module, "SetThreadpoolThreadMaximum");
+ HMODULE kernel32 = LoadLibraryA("kernel32.dll");
+ if (kernel32)
+ {
+ pCreateThreadpool = (void*)GetProcAddress(kernel32, "CreateThreadpool");
+ pCloseThreadpool = (void*)GetProcAddress(kernel32, "CloseThreadpool");
+ pSetThreadpoolThreadMinimum = (void*)GetProcAddress(kernel32, "SetThreadpoolThreadMinimum");
+ pSetThreadpoolThreadMaximum = (void*)GetProcAddress(kernel32, "SetThreadpoolThreadMaximum");
+ }
+ return TRUE;
}
-
-#else
+#endif
static TP_POOL DEFAULT_POOL =
{
fail_queue_new:
return FALSE;
-
}
PTP_POOL GetDefaultThreadpool()
return pool;
}
-#endif
-
-#ifdef WINPR_THREAD_POOL
-
PTP_POOL CreateThreadpool(PVOID reserved)
{
PTP_POOL pool = NULL;
-
#ifdef _WIN32
- module_init();
-
+ InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL);
if (pCreateThreadpool)
return pCreateThreadpool(reserved);
-#else
+#endif
if (!(pool = (PTP_POOL) calloc(1, sizeof(TP_POOL))))
return NULL;
free(pool);
return NULL;
}
-#endif
return pool;
}
VOID CloseThreadpool(PTP_POOL ptpp)
{
#ifdef _WIN32
- module_init();
-
+ InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL);
if (pCloseThreadpool)
+ {
pCloseThreadpool(ptpp);
-#else
+ return;
+ }
+#endif
SetEvent(ptpp->TerminateEvent);
ArrayList_Free(ptpp->Threads);
{
free(ptpp);
}
-#endif
}
BOOL SetThreadpoolThreadMinimum(PTP_POOL ptpp, DWORD cthrdMic)
{
+ HANDLE thread;
#ifdef _WIN32
- module_init();
-
+ InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL);
if (pSetThreadpoolThreadMinimum)
return pSetThreadpoolThreadMinimum(ptpp, cthrdMic);
-#else
- HANDLE thread;
-
+#endif
ptpp->Minimum = cthrdMic;
while (ArrayList_Count(ptpp->Threads) < ptpp->Minimum)
if (ArrayList_Add(ptpp->Threads, thread) < 0)
return FALSE;
}
-#endif
+
return TRUE;
}
VOID SetThreadpoolThreadMaximum(PTP_POOL ptpp, DWORD cthrdMost)
{
#ifdef _WIN32
- module_init();
-
+ InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL);
if (pSetThreadpoolThreadMaximum)
+ {
pSetThreadpoolThreadMaximum(ptpp, cthrdMost);
-#else
- ptpp->Maximum = cthrdMost;
+ return;
+ }
#endif
+ ptpp->Maximum = cthrdMost;
}
-#endif
-
-/* dummy */
-
-void winpr_pool_dummy()
-{
-
-}
+#endif /* WINPR_THREAD_POOL defined */
void* dummy;
};
-#ifndef _WIN32
-
-PTP_POOL GetDefaultThreadpool(void);
-PTP_CALLBACK_ENVIRON GetDefaultThreadpoolEnvironment(void);
-
-#endif
+PTP_POOL GetDefaultThreadpool();
#endif /* WINPR_POOL_PRIVATE_H */
BYTE b[1024];
BYTE c[1024];
- printf("Hello %s: %d (thread: %d)\n", (char*) context,
+ printf("Hello %s: %3d (thread: 0x%08X)\n", (char*) context,
InterlockedIncrement(&count), GetCurrentThreadId());
for (index = 0; index < 100; index++)
DestroyThreadpoolEnvironment(&environment);
- CloseThreadpoolWork(work);
+ /**
+ * See Remarks at https://msdn.microsoft.com/en-us/library/windows/desktop/ms682043(v=vs.85).aspx
+ * If there is a cleanup group associated with the work object,
+ * it is not necessary to call CloseThreadpoolWork !
+ * calling the CloseThreadpoolCleanupGroupMembers function releases the work, wait,
+ * and timer objects associated with the cleanup group.
+ */
+
+ /* CloseThreadpoolWork(work); // this would segfault, see comment above. */
+
CloseThreadpool(pool);
return 0;
#include "../log.h"
#define TAG WINPR_TAG("pool")
-#ifdef _WIN32
-
-static BOOL module_initialized = FALSE;
-static BOOL module_available = FALSE;
-static HMODULE kernel32_module = NULL;
+#ifdef WINPR_THREAD_POOL
+#ifdef _WIN32
+static INIT_ONCE init_once_module = INIT_ONCE_STATIC_INIT;
static PTP_WORK(WINAPI* pCreateThreadpoolWork)(PTP_WORK_CALLBACK pfnwk, PVOID pv, PTP_CALLBACK_ENVIRON pcbe);
static VOID (WINAPI* pCloseThreadpoolWork)(PTP_WORK pwk);
static VOID (WINAPI* pSubmitThreadpoolWork)(PTP_WORK pwk);
static BOOL (WINAPI* pTrySubmitThreadpoolCallback)(PTP_SIMPLE_CALLBACK pfns, PVOID pv, PTP_CALLBACK_ENVIRON pcbe);
static VOID (WINAPI* pWaitForThreadpoolWorkCallbacks)(PTP_WORK pwk, BOOL fCancelPendingCallbacks);
-static void module_init()
+static BOOL CALLBACK init_module(PINIT_ONCE once, PVOID param, PVOID *context)
{
- if (module_initialized)
- return;
-
- kernel32_module = LoadLibraryA("kernel32.dll");
- module_initialized = TRUE;
-
- if (!kernel32_module)
- return;
-
- module_available = TRUE;
- pCreateThreadpoolWork = (void*) GetProcAddress(kernel32_module, "CreateThreadpoolWork");
- pCloseThreadpoolWork = (void*) GetProcAddress(kernel32_module, "CloseThreadpoolWork");
- pSubmitThreadpoolWork = (void*) GetProcAddress(kernel32_module, "SubmitThreadpoolWork");
- pTrySubmitThreadpoolCallback = (void*) GetProcAddress(kernel32_module, "TrySubmitThreadpoolCallback");
- pWaitForThreadpoolWorkCallbacks = (void*) GetProcAddress(kernel32_module, "WaitForThreadpoolWorkCallbacks");
+ HMODULE kernel32 = LoadLibraryA("kernel32.dll");
+ if (kernel32)
+ {
+ pCreateThreadpoolWork = (void*)GetProcAddress(kernel32, "CreateThreadpoolWork");
+ pCloseThreadpoolWork = (void*)GetProcAddress(kernel32, "CloseThreadpoolWork");
+ pSubmitThreadpoolWork = (void*)GetProcAddress(kernel32, "SubmitThreadpoolWork");
+ pTrySubmitThreadpoolCallback = (void*)GetProcAddress(kernel32, "TrySubmitThreadpoolCallback");
+ pWaitForThreadpoolWorkCallbacks = (void*)GetProcAddress(kernel32, "WaitForThreadpoolWorkCallbacks");
+ }
+ return TRUE;
}
-
#endif
-#ifdef WINPR_THREAD_POOL
+static TP_CALLBACK_ENVIRON DEFAULT_CALLBACK_ENVIRONMENT =
+{
+ 1, /* Version */
+ NULL, /* Pool */
+ NULL, /* CleanupGroup */
+ NULL, /* CleanupGroupCancelCallback */
+ NULL, /* RaceDll */
+ NULL, /* ActivationContext */
+ NULL, /* FinalizationCallback */
+ { 0 } /* Flags */
+};
PTP_WORK CreateThreadpoolWork(PTP_WORK_CALLBACK pfnwk, PVOID pv, PTP_CALLBACK_ENVIRON pcbe)
{
PTP_WORK work = NULL;
#ifdef _WIN32
- module_init();
-
+ InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL);
if (pCreateThreadpoolWork)
return pCreateThreadpoolWork(pfnwk, pv, pcbe);
-
-#else
+#endif
work = (PTP_WORK) malloc(sizeof(TP_WORK));
if (work)
{
- work->WorkCallback = pfnwk;
- work->CallbackParameter = pv;
-
if (!pcbe)
- pcbe = GetDefaultThreadpoolEnvironment();
-
+ {
+ pcbe = &DEFAULT_CALLBACK_ENVIRONMENT;
+ pcbe->Pool = GetDefaultThreadpool();
+ }
work->CallbackEnvironment = pcbe;
+ work->WorkCallback = pfnwk;
+ work->CallbackParameter = pv;
}
-#endif
return work;
}
VOID CloseThreadpoolWork(PTP_WORK pwk)
{
#ifdef _WIN32
- module_init();
-
+ InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL);
if (pCloseThreadpoolWork)
+ {
pCloseThreadpoolWork(pwk);
-
-#else
- free(pwk);
+ return;
+ }
#endif
+ free(pwk);
}
VOID SubmitThreadpoolWork(PTP_WORK pwk)
{
+ PTP_POOL pool;
+ PTP_CALLBACK_INSTANCE callbackInstance;
#ifdef _WIN32
- module_init();
-
+ InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL);
if (pSubmitThreadpoolWork)
+ {
pSubmitThreadpoolWork(pwk);
-
-#else
- PTP_POOL pool;
- PTP_CALLBACK_INSTANCE callbackInstance;
+ return;
+ }
+#endif
pool = pwk->CallbackEnvironment->Pool;
callbackInstance = (PTP_CALLBACK_INSTANCE) malloc(sizeof(TP_CALLBACK_INSTANCE));
CountdownEvent_AddCount(pool->WorkComplete, 1);
Queue_Enqueue(pool->PendingQueue, callbackInstance);
}
-
-#endif
}
BOOL TrySubmitThreadpoolCallback(PTP_SIMPLE_CALLBACK pfns, PVOID pv, PTP_CALLBACK_ENVIRON pcbe)
{
#ifdef _WIN32
- module_init();
-
+ InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL);
if (pTrySubmitThreadpoolCallback)
return pTrySubmitThreadpoolCallback(pfns, pv, pcbe);
-
-#else
#endif
+ WLog_ERR(TAG, "TrySubmitThreadpoolCallback is not implemented");
return FALSE;
}
VOID WaitForThreadpoolWorkCallbacks(PTP_WORK pwk, BOOL fCancelPendingCallbacks)
{
+ HANDLE event;
+ PTP_POOL pool;
#ifdef _WIN32
- module_init();
-
+ InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL);
if (pWaitForThreadpoolWorkCallbacks)
+ {
pWaitForThreadpoolWorkCallbacks(pwk, fCancelPendingCallbacks);
-
-#else
- HANDLE event;
- PTP_POOL pool;
+ return;
+ }
+#endif
pool = pwk->CallbackEnvironment->Pool;
event = CountdownEvent_WaitHandle(pool->WorkComplete);
if (WaitForSingleObject(event, INFINITE) != WAIT_OBJECT_0)
WLog_ERR(TAG, "error waiting on work completion");
-
-#endif
}
-#endif
+#endif /* WINPR_THREAD_POOL defined */
}
#endif
-
-#ifdef WINPR_INITIALIZE_CRITICAL_SECTION_EX
-
-typedef BOOL (WINAPI* PINITIALIZE_CRITICAL_SECTION_EX_FN)(LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount, DWORD Flags);
-
-static HMODULE g_KERNEL32_Library = NULL;
-static BOOL g_InitializeCriticalSectionEx_Detected = FALSE;
-static BOOL g_InitializeCriticalSectionEx_Available = FALSE;
-static PINITIALIZE_CRITICAL_SECTION_EX_FN g_pInitializeCriticalSectionEx = NULL;
-
-BOOL InitializeCriticalSectionEx(LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount, DWORD Flags)
-{
- if (!g_InitializeCriticalSectionEx_Detected)
- {
- g_KERNEL32_Library = LoadLibrary(_T("kernel32.dll"));
-
- if (g_KERNEL32_Library)
- {
- g_pInitializeCriticalSectionEx = (PINITIALIZE_CRITICAL_SECTION_EX_FN)
- GetProcAddress(g_KERNEL32_Library, "InitializeCriticalSectionEx");
- g_InitializeCriticalSectionEx_Available = (g_pInitializeCriticalSectionEx) ? TRUE : FALSE;
- }
- else
- {
- g_InitializeCriticalSectionEx_Available = FALSE;
- }
-
- g_InitializeCriticalSectionEx_Detected = TRUE;
- }
-
- if (g_InitializeCriticalSectionEx_Available)
- {
- /* Vista and later */
- return (*g_pInitializeCriticalSectionEx)(lpCriticalSection, dwSpinCount, Flags);
- }
- else
- {
- /* Windows XP */
- InitializeCriticalSection(lpCriticalSection);
- }
-
- return TRUE;
-}
-
-#endif