Coverage Report

Created: 2026-02-26 06:54

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/FreeRDP/winpr/libwinpr/utils/collections/ObjectPool.c
Line
Count
Source
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
11.0k
{
48
11.0k
  WINPR_ASSERT(pool);
49
11.0k
  if (pool->synchronized)
50
11.0k
    EnterCriticalSection(&pool->lock);
51
11.0k
}
52
53
static void ObjectPool_Unlock(wObjectPool* pool)
54
11.0k
{
55
11.0k
  WINPR_ASSERT(pool);
56
11.0k
  if (pool->synchronized)
57
11.0k
    LeaveCriticalSection(&pool->lock);
58
11.0k
}
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
  WINPR_ASSERT(pool->size < SIZE_MAX);
96
0
  const size_t required = pool->size + 1ull;
97
0
  if (required >= pool->capacity)
98
0
  {
99
0
    size_t new_cap = pool->capacity;
100
0
    do
101
0
    {
102
0
      WINPR_ASSERT(new_cap <= SIZE_MAX - 128ull);
103
0
      new_cap += 128ull;
104
0
    } while (new_cap <= required);
105
106
0
    void** new_arr = (void**)realloc((void*)pool->array, sizeof(void*) * new_cap);
107
0
    if (!new_arr)
108
0
      goto out;
109
110
0
    pool->array = new_arr;
111
0
    pool->capacity = new_cap;
112
0
  }
113
114
0
  pool->array[(pool->size)++] = obj;
115
116
0
  if (pool->object.fnObjectUninit)
117
0
    pool->object.fnObjectUninit(obj);
118
119
0
out:
120
0
  ObjectPool_Unlock(pool);
121
0
}
122
123
wObject* ObjectPool_Object(wObjectPool* pool)
124
11.0k
{
125
11.0k
  WINPR_ASSERT(pool);
126
11.0k
  return &pool->object;
127
11.0k
}
128
129
/**
130
 * Releases the buffers currently cached in the pool.
131
 */
132
133
void ObjectPool_Clear(wObjectPool* pool)
134
11.0k
{
135
11.0k
  ObjectPool_Lock(pool);
136
137
11.0k
  while (pool->size > 0)
138
0
  {
139
0
    (pool->size)--;
140
141
0
    if (pool->object.fnObjectFree)
142
0
      pool->object.fnObjectFree(pool->array[pool->size]);
143
0
  }
144
145
11.0k
  ObjectPool_Unlock(pool);
146
11.0k
}
147
148
/**
149
 * Construction, Destruction
150
 */
151
152
wObjectPool* ObjectPool_New(BOOL synchronized)
153
11.0k
{
154
11.0k
  wObjectPool* pool = NULL;
155
156
11.0k
  pool = (wObjectPool*)calloc(1, sizeof(wObjectPool));
157
158
11.0k
  if (pool)
159
11.0k
  {
160
11.0k
    pool->capacity = 32;
161
11.0k
    pool->size = 0;
162
11.0k
    pool->array = (void**)calloc(pool->capacity, sizeof(void*));
163
11.0k
    if (!pool->array)
164
0
    {
165
0
      free(pool);
166
0
      return NULL;
167
0
    }
168
11.0k
    pool->synchronized = synchronized;
169
170
11.0k
    if (pool->synchronized)
171
11.0k
      InitializeCriticalSectionAndSpinCount(&pool->lock, 4000);
172
11.0k
  }
173
174
11.0k
  return pool;
175
11.0k
}
176
177
void ObjectPool_Free(wObjectPool* pool)
178
11.0k
{
179
11.0k
  if (pool)
180
11.0k
  {
181
11.0k
    ObjectPool_Clear(pool);
182
183
11.0k
    if (pool->synchronized)
184
11.0k
      DeleteCriticalSection(&pool->lock);
185
186
11.0k
    free((void*)pool->array);
187
188
11.0k
    free(pool);
189
11.0k
  }
190
11.0k
}