2
* WinPR: Windows Portable Runtime
3
* Reference Count Table
5
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
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
11
* http://www.apache.org/licenses/LICENSE-2.0
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.
28
#include <winpr/crt.h>
30
#include <winpr/collections.h>
33
* C reference counting
34
* http://msdn.microsoft.com/en-us/library/windows/desktop/ms693431/
37
wReference* ReferenceTable_FindEntry(wReferenceTable* referenceTable, void* ptr)
41
wReference* reference = NULL;
43
for (index = 0; index < referenceTable->size; index++)
45
reference = &referenceTable->array[index];
47
if (reference->Pointer == ptr)
51
return (found) ? reference : NULL;
54
wReference* ReferenceTable_GetFreeEntry(wReferenceTable* referenceTable)
58
wReference* reference = NULL;
60
for (index = 0; index < referenceTable->size; index++)
62
reference = &referenceTable->array[index];
64
if (reference->Pointer == NULL)
73
referenceTable->size *= 2;
74
referenceTable->array = (wReference*) realloc(referenceTable->array, sizeof(wReference) * referenceTable->size);
76
ZeroMemory(&referenceTable->array[(referenceTable->size / 2)],
77
sizeof(wReference) * (referenceTable->size / 2));
79
return ReferenceTable_GetFreeEntry(referenceTable);
85
UINT32 ReferenceTable_Add(wReferenceTable* referenceTable, void* ptr)
88
wReference* reference = NULL;
90
if (referenceTable->synchronized)
91
EnterCriticalSection(&referenceTable->lock);
93
reference = ReferenceTable_FindEntry(referenceTable, ptr);
97
reference = ReferenceTable_GetFreeEntry(referenceTable);
98
reference->Pointer = ptr;
102
count = ++(reference->Count);
104
if (referenceTable->synchronized)
105
LeaveCriticalSection(&referenceTable->lock);
110
UINT32 ReferenceTable_Release(wReferenceTable* referenceTable, void* ptr)
113
wReference* reference = NULL;
115
if (referenceTable->synchronized)
116
EnterCriticalSection(&referenceTable->lock);
118
reference = ReferenceTable_FindEntry(referenceTable, ptr);
122
count = --(reference->Count);
126
if (referenceTable->ReferenceFree)
128
referenceTable->ReferenceFree(referenceTable->context, ptr);
129
reference->Pointer = NULL;
130
reference->Count = 0;
135
if (referenceTable->synchronized)
136
LeaveCriticalSection(&referenceTable->lock);
141
wReferenceTable* ReferenceTable_New(BOOL synchronized, void* context, REFERENCE_FREE ReferenceFree)
143
wReferenceTable* referenceTable;
145
referenceTable = (wReferenceTable*) malloc(sizeof(wReferenceTable));
149
referenceTable->context = context;
150
referenceTable->ReferenceFree = ReferenceFree;
152
referenceTable->size = 32;
153
referenceTable->array = (wReference*) malloc(sizeof(wReference) * referenceTable->size);
154
ZeroMemory(referenceTable->array, sizeof(wReference) * referenceTable->size);
156
referenceTable->synchronized = synchronized;
157
InitializeCriticalSectionAndSpinCount(&referenceTable->lock, 4000);
160
return referenceTable;
163
void ReferenceTable_Free(wReferenceTable* referenceTable)
167
DeleteCriticalSection(&referenceTable->lock);
168
free(referenceTable->array);
169
free(referenceTable);