Coverage Report

Created: 2025-07-01 06:46

/src/FreeRDP/winpr/libwinpr/utils/collections/ObjectPool.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * WinPR: Windows Portable Runtime
3
 * Object Pool
4
 *
5
 * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6
 *
7
 * Licensed under the Apache License, Version 2.0 (the "License");
8
 * you may not use this file except in compliance with the License.
9
 * You may obtain a copy of the License at
10
 *
11
 *     http://www.apache.org/licenses/LICENSE-2.0
12
 *
13
 * Unless required by applicable law or agreed to in writing, software
14
 * distributed under the License is distributed on an "AS IS" BASIS,
15
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 * See the License for the specific language governing permissions and
17
 * limitations under the License.
18
 */
19
20
#include <winpr/config.h>
21
22
#include <winpr/crt.h>
23
#include <winpr/assert.h>
24
25
#include <winpr/collections.h>
26
27
struct s_wObjectPool
28
{
29
  size_t size;
30
  size_t capacity;
31
  void** array;
32
  CRITICAL_SECTION lock;
33
  wObject object;
34
  BOOL synchronized;
35
};
36
37
/**
38
 * C Object Pool similar to C# BufferManager Class:
39
 * http://msdn.microsoft.com/en-us/library/ms405814.aspx
40
 */
41
42
/**
43
 * Methods
44
 */
45
46
static void ObjectPool_Lock(wObjectPool* pool)
47
0
{
48
0
  WINPR_ASSERT(pool);
49
0
  if (pool->synchronized)
50
0
    EnterCriticalSection(&pool->lock);
51
0
}
52
53
static void ObjectPool_Unlock(wObjectPool* pool)
54
0
{
55
0
  WINPR_ASSERT(pool);
56
0
  if (pool->synchronized)
57
0
    LeaveCriticalSection(&pool->lock);
58
0
}
59
60
/**
61
 * Gets an object from the pool.
62
 */
63
64
void* ObjectPool_Take(wObjectPool* pool)
65
0
{
66
0
  void* obj = NULL;
67
68
0
  ObjectPool_Lock(pool);
69
70
0
  if (pool->size > 0)
71
0
    obj = pool->array[--(pool->size)];
72
73
0
  if (!obj)
74
0
  {
75
0
    if (pool->object.fnObjectNew)
76
0
      obj = pool->object.fnObjectNew(NULL);
77
0
  }
78
79
0
  if (pool->object.fnObjectInit)
80
0
    pool->object.fnObjectInit(obj);
81
82
0
  ObjectPool_Unlock(pool);
83
84
0
  return obj;
85
0
}
86
87
/**
88
 * Returns an object to the pool.
89
 */
90
91
void ObjectPool_Return(wObjectPool* pool, void* obj)
92
0
{
93
0
  ObjectPool_Lock(pool);
94
95
0
  if ((pool->size + 1) >= pool->capacity)
96
0
  {
97
0
    size_t new_cap = 0;
98
0
    void** new_arr = NULL;
99
100
0
    new_cap = pool->capacity * 2;
101
0
    new_arr = (void**)realloc((void*)pool->array, sizeof(void*) * new_cap);
102
0
    if (!new_arr)
103
0
      goto out;
104
105
0
    pool->array = new_arr;
106
0
    pool->capacity = new_cap;
107
0
  }
108
109
0
  pool->array[(pool->size)++] = obj;
110
111
0
  if (pool->object.fnObjectUninit)
112
0
    pool->object.fnObjectUninit(obj);
113
114
0
out:
115
0
  ObjectPool_Unlock(pool);
116
0
}
117
118
wObject* ObjectPool_Object(wObjectPool* pool)
119
0
{
120
0
  WINPR_ASSERT(pool);
121
0
  return &pool->object;
122
0
}
123
124
/**
125
 * Releases the buffers currently cached in the pool.
126
 */
127
128
void ObjectPool_Clear(wObjectPool* pool)
129
0
{
130
0
  ObjectPool_Lock(pool);
131
132
0
  while (pool->size > 0)
133
0
  {
134
0
    (pool->size)--;
135
136
0
    if (pool->object.fnObjectFree)
137
0
      pool->object.fnObjectFree(pool->array[pool->size]);
138
0
  }
139
140
0
  ObjectPool_Unlock(pool);
141
0
}
142
143
/**
144
 * Construction, Destruction
145
 */
146
147
wObjectPool* ObjectPool_New(BOOL synchronized)
148
0
{
149
0
  wObjectPool* pool = NULL;
150
151
0
  pool = (wObjectPool*)calloc(1, sizeof(wObjectPool));
152
153
0
  if (pool)
154
0
  {
155
0
    pool->capacity = 32;
156
0
    pool->size = 0;
157
0
    pool->array = (void**)calloc(pool->capacity, sizeof(void*));
158
0
    if (!pool->array)
159
0
    {
160
0
      free(pool);
161
0
      return NULL;
162
0
    }
163
0
    pool->synchronized = synchronized;
164
165
0
    if (pool->synchronized)
166
0
      InitializeCriticalSectionAndSpinCount(&pool->lock, 4000);
167
0
  }
168
169
0
  return pool;
170
0
}
171
172
void ObjectPool_Free(wObjectPool* pool)
173
0
{
174
0
  if (pool)
175
0
  {
176
0
    ObjectPool_Clear(pool);
177
178
0
    if (pool->synchronized)
179
0
      DeleteCriticalSection(&pool->lock);
180
181
0
    free((void*)pool->array);
182
183
0
    free(pool);
184
0
  }
185
0
}