FreeRDP
cleanup_group.c
1 
20 #include <winpr/config.h>
21 
22 #include <winpr/winpr.h>
23 #include <winpr/crt.h>
24 #include <winpr/pool.h>
25 #include <winpr/library.h>
26 
27 #include "pool.h"
28 
29 #ifdef WINPR_THREAD_POOL
30 
31 #ifdef _WIN32
32 static INIT_ONCE init_once_module = INIT_ONCE_STATIC_INIT;
33 static PTP_CLEANUP_GROUP(WINAPI* pCreateThreadpoolCleanupGroup)();
34 static VOID(WINAPI* pCloseThreadpoolCleanupGroupMembers)(PTP_CLEANUP_GROUP ptpcg,
35  BOOL fCancelPendingCallbacks,
36  PVOID pvCleanupContext);
37 static VOID(WINAPI* pCloseThreadpoolCleanupGroup)(PTP_CLEANUP_GROUP ptpcg);
38 
39 static BOOL CALLBACK init_module(PINIT_ONCE once, PVOID param, PVOID* context)
40 {
41  HMODULE kernel32 = LoadLibraryA("kernel32.dll");
42 
43  if (kernel32)
44  {
45  pCreateThreadpoolCleanupGroup =
46  GetProcAddressAs(kernel32, "CreateThreadpoolCleanupGroup", void*);
47  pCloseThreadpoolCleanupGroupMembers =
48  GetProcAddressAs(kernel32, "CloseThreadpoolCleanupGroupMembers", void*);
49  pCloseThreadpoolCleanupGroup =
50  GetProcAddressAs(kernel32, "CloseThreadpoolCleanupGroup", void*);
51  }
52 
53  return TRUE;
54 }
55 #endif
56 
57 PTP_CLEANUP_GROUP winpr_CreateThreadpoolCleanupGroup(void)
58 {
59  PTP_CLEANUP_GROUP cleanupGroup = NULL;
60 #ifdef _WIN32
61  InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL);
62 
63  if (pCreateThreadpoolCleanupGroup)
64  return pCreateThreadpoolCleanupGroup();
65 
66  return cleanupGroup;
67 #else
68  cleanupGroup = (PTP_CLEANUP_GROUP)calloc(1, sizeof(TP_CLEANUP_GROUP));
69 
70  if (!cleanupGroup)
71  return NULL;
72 
73  cleanupGroup->groups = ArrayList_New(FALSE);
74 
75  if (!cleanupGroup->groups)
76  {
77  free(cleanupGroup);
78  return NULL;
79  }
80 
81  return cleanupGroup;
82 #endif
83 }
84 
85 VOID winpr_SetThreadpoolCallbackCleanupGroup(PTP_CALLBACK_ENVIRON pcbe, PTP_CLEANUP_GROUP ptpcg,
86  PTP_CLEANUP_GROUP_CANCEL_CALLBACK pfng)
87 {
88  pcbe->CleanupGroup = ptpcg;
89  pcbe->CleanupGroupCancelCallback = pfng;
90 #ifndef _WIN32
91  pcbe->CleanupGroup->env = pcbe;
92 #endif
93 }
94 
95 VOID winpr_CloseThreadpoolCleanupGroupMembers(PTP_CLEANUP_GROUP ptpcg, BOOL fCancelPendingCallbacks,
96  PVOID pvCleanupContext)
97 {
98 #ifdef _WIN32
99  InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL);
100 
101  if (pCloseThreadpoolCleanupGroupMembers)
102  {
103  pCloseThreadpoolCleanupGroupMembers(ptpcg, fCancelPendingCallbacks, pvCleanupContext);
104  return;
105  }
106 
107 #else
108 
109  while (ArrayList_Count(ptpcg->groups) > 0)
110  {
111  PTP_WORK work = ArrayList_GetItem(ptpcg->groups, 0);
112  winpr_CloseThreadpoolWork(work);
113  }
114 
115 #endif
116 }
117 
118 VOID winpr_CloseThreadpoolCleanupGroup(PTP_CLEANUP_GROUP ptpcg)
119 {
120 #ifdef _WIN32
121  InitOnceExecuteOnce(&init_once_module, init_module, NULL, NULL);
122 
123  if (pCloseThreadpoolCleanupGroup)
124  {
125  pCloseThreadpoolCleanupGroup(ptpcg);
126  return;
127  }
128 
129 #else
130 
131  if (ptpcg && ptpcg->groups)
132  ArrayList_Free(ptpcg->groups);
133 
134  if (ptpcg && ptpcg->env)
135  ptpcg->env->CleanupGroup = NULL;
136 
137  free(ptpcg);
138 #endif
139 }
140 
141 #endif /* WINPR_THREAD_POOL defined */