~ubuntu-branches/ubuntu/vivid/freerdp/vivid

« back to all changes in this revision

Viewing changes to winpr/libwinpr/utils/collections/Reference.c

  • Committer: Package Import Robot
  • Author(s): Iain Lane
  • Date: 2014-11-11 12:20:50 UTC
  • mfrom: (1.2.5)
  • mto: This revision was merged to the branch mainline in revision 24.
  • Revision ID: package-import@ubuntu.com-20141111122050-7z628f4ab38qxad5
Tags: upstream-1.1.0~git20140921.1.440916e+dfsg1
ImportĀ upstreamĀ versionĀ 1.1.0~git20140921.1.440916e+dfsg1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * WinPR: Windows Portable Runtime
 
3
 * Reference Count Table
 
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
#ifdef HAVE_CONFIG_H
 
21
#include "config.h"
 
22
#endif
 
23
 
 
24
#ifdef HAVE_UNISTD_H
 
25
#include <unistd.h>
 
26
#endif
 
27
 
 
28
#include <winpr/crt.h>
 
29
 
 
30
#include <winpr/collections.h>
 
31
 
 
32
/**
 
33
 * C reference counting
 
34
 * http://msdn.microsoft.com/en-us/library/windows/desktop/ms693431/
 
35
 */
 
36
 
 
37
wReference* ReferenceTable_FindEntry(wReferenceTable* referenceTable, void* ptr)
 
38
{
 
39
        int index = 0;
 
40
        BOOL found = FALSE;
 
41
        wReference* reference = NULL;
 
42
 
 
43
        for (index = 0; index < referenceTable->size; index++)
 
44
        {
 
45
                reference = &referenceTable->array[index];
 
46
 
 
47
                if (reference->Pointer == ptr)
 
48
                        found = TRUE;
 
49
        }
 
50
 
 
51
        return (found) ? reference : NULL;
 
52
}
 
53
 
 
54
wReference* ReferenceTable_GetFreeEntry(wReferenceTable* referenceTable)
 
55
{
 
56
        int index = 0;
 
57
        BOOL found = FALSE;
 
58
        wReference* reference = NULL;
 
59
 
 
60
        for (index = 0; index < referenceTable->size; index++)
 
61
        {
 
62
                reference = &referenceTable->array[index];
 
63
 
 
64
                if (reference->Pointer == NULL)
 
65
                {
 
66
                        reference->Count = 0;
 
67
                        found = TRUE;
 
68
                }
 
69
        }
 
70
 
 
71
        if (!found)
 
72
        {
 
73
                referenceTable->size *= 2;
 
74
                referenceTable->array = (wReference*) realloc(referenceTable->array, sizeof(wReference) * referenceTable->size);
 
75
 
 
76
                ZeroMemory(&referenceTable->array[(referenceTable->size / 2)],
 
77
                                sizeof(wReference) * (referenceTable->size / 2));
 
78
 
 
79
                return ReferenceTable_GetFreeEntry(referenceTable);
 
80
        }
 
81
 
 
82
        return reference;
 
83
}
 
84
 
 
85
UINT32 ReferenceTable_Add(wReferenceTable* referenceTable, void* ptr)
 
86
{
 
87
        UINT32 count = 0;
 
88
        wReference* reference = NULL;
 
89
 
 
90
        if (referenceTable->synchronized)
 
91
                EnterCriticalSection(&referenceTable->lock);
 
92
 
 
93
        reference = ReferenceTable_FindEntry(referenceTable, ptr);
 
94
 
 
95
        if (!reference)
 
96
        {
 
97
                reference = ReferenceTable_GetFreeEntry(referenceTable);
 
98
                reference->Pointer = ptr;
 
99
                reference->Count = 0;
 
100
        }
 
101
 
 
102
        count = ++(reference->Count);
 
103
 
 
104
        if (referenceTable->synchronized)
 
105
                LeaveCriticalSection(&referenceTable->lock);
 
106
 
 
107
        return count;
 
108
}
 
109
 
 
110
UINT32 ReferenceTable_Release(wReferenceTable* referenceTable, void* ptr)
 
111
{
 
112
        UINT32 count = 0;
 
113
        wReference* reference = NULL;
 
114
 
 
115
        if (referenceTable->synchronized)
 
116
                EnterCriticalSection(&referenceTable->lock);
 
117
 
 
118
        reference = ReferenceTable_FindEntry(referenceTable, ptr);
 
119
 
 
120
        if (reference)
 
121
        {
 
122
                count = --(reference->Count);
 
123
 
 
124
                if (count < 1)
 
125
                {
 
126
                        if (referenceTable->ReferenceFree)
 
127
                        {
 
128
                                referenceTable->ReferenceFree(referenceTable->context, ptr);
 
129
                                reference->Pointer = NULL;
 
130
                                reference->Count = 0;
 
131
                        }
 
132
                }
 
133
        }
 
134
 
 
135
        if (referenceTable->synchronized)
 
136
                LeaveCriticalSection(&referenceTable->lock);
 
137
 
 
138
        return count;
 
139
}
 
140
 
 
141
wReferenceTable* ReferenceTable_New(BOOL synchronized, void* context, REFERENCE_FREE ReferenceFree)
 
142
{
 
143
        wReferenceTable* referenceTable;
 
144
 
 
145
        referenceTable = (wReferenceTable*) malloc(sizeof(wReferenceTable));
 
146
 
 
147
        if (referenceTable)
 
148
        {
 
149
                referenceTable->context = context;
 
150
                referenceTable->ReferenceFree = ReferenceFree;
 
151
 
 
152
                referenceTable->size = 32;
 
153
                referenceTable->array = (wReference*) malloc(sizeof(wReference) * referenceTable->size);
 
154
                ZeroMemory(referenceTable->array, sizeof(wReference) * referenceTable->size);
 
155
 
 
156
                referenceTable->synchronized = synchronized;
 
157
                InitializeCriticalSectionAndSpinCount(&referenceTable->lock, 4000);
 
158
        }
 
159
 
 
160
        return referenceTable;
 
161
}
 
162
 
 
163
void ReferenceTable_Free(wReferenceTable* referenceTable)
 
164
{
 
165
        if (referenceTable)
 
166
        {
 
167
                DeleteCriticalSection(&referenceTable->lock);
 
168
                free(referenceTable->array);
 
169
                free(referenceTable);
 
170
        }
 
171
}