FreeRDP
Loading...
Searching...
No Matches
ObjectPool.c
1
20#include <winpr/config.h>
21
22#include <winpr/crt.h>
23#include <winpr/assert.h>
24
25#include <winpr/collections.h>
26
27struct s_wObjectPool
28{
29 size_t size;
30 size_t capacity;
31 void** array;
33 wObject object;
34 BOOL synchronized;
35};
36
46static void ObjectPool_Lock(wObjectPool* pool)
47{
48 WINPR_ASSERT(pool);
49 if (pool->synchronized)
50 EnterCriticalSection(&pool->lock);
51}
52
53static void ObjectPool_Unlock(wObjectPool* pool)
54{
55 WINPR_ASSERT(pool);
56 if (pool->synchronized)
57 LeaveCriticalSection(&pool->lock);
58}
59
64void* ObjectPool_Take(wObjectPool* pool)
65{
66 void* obj = nullptr;
67
68 ObjectPool_Lock(pool);
69
70 if (pool->size > 0)
71 obj = pool->array[--(pool->size)];
72
73 if (!obj)
74 {
75 if (pool->object.fnObjectNew)
76 obj = pool->object.fnObjectNew(nullptr);
77 }
78
79 if (pool->object.fnObjectInit)
80 pool->object.fnObjectInit(obj);
81
82 ObjectPool_Unlock(pool);
83
84 return obj;
85}
86
87static BOOL ObjectPool_EnsureCapacity(wObjectPool* pool, size_t add)
88{
89 WINPR_ASSERT(pool->size < SIZE_MAX - add);
90
91 const size_t blocksize = 128ull;
92 const size_t required = pool->size + add;
93 if (required >= pool->capacity)
94 {
95 const size_t new_cap = required + blocksize - required % blocksize;
96
97 void** new_arr = (void**)realloc((void*)pool->array, sizeof(void*) * new_cap);
98 if (!new_arr)
99 return FALSE;
100
101 pool->array = new_arr;
102 pool->capacity = new_cap;
103 }
104 return TRUE;
105}
106
111void ObjectPool_Return(wObjectPool* pool, void* obj)
112{
113 ObjectPool_Lock(pool);
114
115 if (!ObjectPool_EnsureCapacity(pool, 1))
116 goto out;
117
118 pool->array[(pool->size)++] = obj;
119
120 if (pool->object.fnObjectUninit)
121 pool->object.fnObjectUninit(obj);
122
123out:
124 ObjectPool_Unlock(pool);
125}
126
127wObject* ObjectPool_Object(wObjectPool* pool)
128{
129 WINPR_ASSERT(pool);
130 return &pool->object;
131}
132
137void ObjectPool_Clear(wObjectPool* pool)
138{
139 ObjectPool_Lock(pool);
140
141 while (pool->size > 0)
142 {
143 (pool->size)--;
144
145 if (pool->object.fnObjectFree)
146 pool->object.fnObjectFree(pool->array[pool->size]);
147 }
148
149 ObjectPool_Unlock(pool);
150}
151
156wObjectPool* ObjectPool_New(BOOL synchronized)
157{
158 wObjectPool* pool = (wObjectPool*)calloc(1, sizeof(wObjectPool));
159
160 if (!pool)
161 goto fail;
162
163 pool->synchronized = synchronized;
164
165 if (pool->synchronized)
166 {
167 if (!InitializeCriticalSectionAndSpinCount(&pool->lock, 4000))
168 goto fail;
169 }
170
171 if (!ObjectPool_EnsureCapacity(pool, 32))
172 goto fail;
173
174 return pool;
175
176fail:
177 ObjectPool_Free(pool);
178 return nullptr;
179}
180
181void ObjectPool_Free(wObjectPool* pool)
182{
183 if (!pool)
184 return;
185
186 ObjectPool_Clear(pool);
187
188 if (pool->synchronized)
189 DeleteCriticalSection(&pool->lock);
190
191 free((void*)pool->array);
192
193 free(pool);
194}
This struct contains function pointer to initialize/free objects.
Definition collections.h:52
OBJECT_NEW_FN fnObjectNew
Definition collections.h:53