/src/S2OPC/src/Common/helpers/sopc_tsafe_dict.c
Line | Count | Source |
1 | | /* |
2 | | * Licensed to Systerel under one or more contributor license |
3 | | * agreements. See the NOTICE file distributed with this work |
4 | | * for additional information regarding copyright ownership. |
5 | | * Systerel licenses this file to you under the Apache |
6 | | * License, Version 2.0 (the "License"); you may not use this |
7 | | * file except in compliance with the License. You may obtain |
8 | | * a copy of the License at |
9 | | * |
10 | | * http://www.apache.org/licenses/LICENSE-2.0 |
11 | | * |
12 | | * Unless required by applicable law or agreed to in writing, |
13 | | * software distributed under the License is distributed on an |
14 | | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
15 | | * KIND, either express or implied. See the License for the |
16 | | * specific language governing permissions and limitations |
17 | | * under the License. |
18 | | */ |
19 | | |
20 | | #include "sopc_tsafe_dict.h" |
21 | | #include "sopc_assert.h" |
22 | | #include "sopc_mem_alloc.h" |
23 | | #include "sopc_mutexes.h" |
24 | | |
25 | | struct _SOPC_TSafe_Dict |
26 | | { |
27 | | SOPC_Mutex lock; |
28 | | SOPC_TSafe_Dict_KeyCopy_Fct* copy_func; |
29 | | SOPC_Dict* dict; |
30 | | }; |
31 | | |
32 | | SOPC_TSafe_Dict* SOPC_TSafe_Dict_Create(uintptr_t empty_key, |
33 | | SOPC_Dict_KeyHash_Fct* key_hash, |
34 | | SOPC_Dict_KeyEqual_Fct* key_equal, |
35 | | SOPC_TSafe_Dict_KeyCopy_Fct* key_copy, |
36 | | SOPC_Dict_Free_Fct* key_free, |
37 | | SOPC_Dict_Free_Fct* value_free) |
38 | 0 | { |
39 | 0 | SOPC_TSafe_Dict* safeDict = SOPC_Calloc(1, sizeof(SOPC_TSafe_Dict)); |
40 | 0 | if (NULL == safeDict) |
41 | 0 | { |
42 | 0 | return NULL; |
43 | 0 | } |
44 | 0 | SOPC_ReturnStatus status = SOPC_Mutex_Initialization(&safeDict->lock); |
45 | 0 | if (SOPC_STATUS_OK == status) |
46 | 0 | { |
47 | 0 | safeDict->copy_func = key_copy; |
48 | |
|
49 | 0 | safeDict->dict = SOPC_Dict_Create(empty_key, key_hash, key_equal, key_free, value_free); |
50 | 0 | if (NULL == safeDict->dict) |
51 | 0 | { |
52 | 0 | status = SOPC_STATUS_NOK; |
53 | 0 | } |
54 | 0 | } |
55 | 0 | if (SOPC_STATUS_OK != status) |
56 | 0 | { |
57 | 0 | SOPC_TSafe_Dict_Delete(safeDict); |
58 | 0 | safeDict = NULL; |
59 | 0 | } |
60 | 0 | return safeDict; |
61 | 0 | } |
62 | | |
63 | | void SOPC_TSafe_Dict_Delete(SOPC_TSafe_Dict* d) |
64 | 0 | { |
65 | 0 | if (NULL != d) |
66 | 0 | { |
67 | 0 | SOPC_Dict_Delete(d->dict); |
68 | 0 | SOPC_Mutex_Clear(&d->lock); |
69 | 0 | SOPC_Free(d); |
70 | 0 | } |
71 | 0 | } |
72 | | |
73 | | bool SOPC_TSafe_Dict_Reserve(SOPC_TSafe_Dict* d, size_t n_items) |
74 | 0 | { |
75 | 0 | if (NULL == d) |
76 | 0 | { |
77 | 0 | return false; |
78 | 0 | } |
79 | 0 | SOPC_Mutex_Lock(&d->lock); |
80 | 0 | bool res = SOPC_Dict_Reserve(d->dict, n_items); |
81 | 0 | SOPC_Mutex_Unlock(&d->lock); |
82 | 0 | return res; |
83 | 0 | } |
84 | | |
85 | | void SOPC_TSafe_Dict_SetTombstoneKey(SOPC_TSafe_Dict* d, uintptr_t tombstone_key) |
86 | 0 | { |
87 | 0 | SOPC_ASSERT(NULL != d); |
88 | 0 | SOPC_Mutex_Lock(&d->lock); |
89 | 0 | SOPC_Dict_SetTombstoneKey(d->dict, tombstone_key); |
90 | 0 | SOPC_Mutex_Unlock(&d->lock); |
91 | 0 | } |
92 | | |
93 | | bool SOPC_TSafe_Dict_Insert(SOPC_TSafe_Dict* d, uintptr_t key, uintptr_t value) |
94 | 0 | { |
95 | 0 | if (NULL == d) |
96 | 0 | { |
97 | 0 | return false; |
98 | 0 | } |
99 | 0 | SOPC_Mutex_Lock(&d->lock); |
100 | 0 | bool res = SOPC_Dict_Insert(d->dict, key, value); |
101 | 0 | SOPC_Mutex_Unlock(&d->lock); |
102 | 0 | return res; |
103 | 0 | } |
104 | | |
105 | | uintptr_t SOPC_TSafe_Dict_GetAndLock(SOPC_TSafe_Dict* d, const uintptr_t key, bool* found) |
106 | 0 | { |
107 | 0 | if (NULL == d) |
108 | 0 | { |
109 | 0 | return (uintptr_t) NULL; |
110 | 0 | } |
111 | 0 | SOPC_Mutex_Lock(&d->lock); |
112 | 0 | uintptr_t result = SOPC_Dict_Get(d->dict, key, found); |
113 | 0 | return result; |
114 | 0 | } |
115 | | |
116 | | uintptr_t SOPC_TSafe_Dict_GetCopy(SOPC_TSafe_Dict* d, const uintptr_t key, bool* found) |
117 | 0 | { |
118 | 0 | if (NULL == d || NULL == d->copy_func) |
119 | 0 | { |
120 | 0 | return (uintptr_t) NULL; |
121 | 0 | } |
122 | 0 | uintptr_t copy = (uintptr_t) NULL; |
123 | 0 | SOPC_Mutex_Lock(&d->lock); |
124 | 0 | uintptr_t result = SOPC_Dict_Get(d->dict, key, found); |
125 | 0 | if ((uintptr_t) NULL != result) |
126 | 0 | { |
127 | 0 | copy = d->copy_func(result); |
128 | 0 | } |
129 | 0 | SOPC_Mutex_Unlock(&d->lock); |
130 | 0 | return copy; |
131 | 0 | } |
132 | | |
133 | | uintptr_t SOPC_TSafe_Dict_GetKeyAndLock(SOPC_TSafe_Dict* d, const uintptr_t key, bool* found) |
134 | 0 | { |
135 | 0 | if (NULL == d) |
136 | 0 | { |
137 | 0 | return (uintptr_t) NULL; |
138 | 0 | } |
139 | 0 | SOPC_Mutex_Lock(&d->lock); |
140 | 0 | uintptr_t result = SOPC_Dict_GetKey(d->dict, key, found); |
141 | 0 | return result; |
142 | 0 | } |
143 | | |
144 | | void SOPC_TSafe_Dict_Unlock(SOPC_TSafe_Dict* d) |
145 | 0 | { |
146 | 0 | SOPC_ASSERT(NULL != d); |
147 | 0 | SOPC_Mutex_Unlock(&d->lock); |
148 | 0 | } |
149 | | |
150 | | void SOPC_TSafe_Dict_Remove(SOPC_TSafe_Dict* d, const uintptr_t key) |
151 | 0 | { |
152 | 0 | SOPC_ASSERT(NULL != d); |
153 | 0 | SOPC_Mutex_Lock(&d->lock); |
154 | 0 | SOPC_Dict_Remove(d->dict, key); |
155 | 0 | SOPC_Mutex_Unlock(&d->lock); |
156 | 0 | } |
157 | | |
158 | | SOPC_Dict_Free_Fct* SOPC_TSafe_Dict_GetKeyFreeFunc(SOPC_TSafe_Dict* d) |
159 | 0 | { |
160 | 0 | if (NULL == d) |
161 | 0 | { |
162 | 0 | return NULL; |
163 | 0 | } |
164 | 0 | SOPC_Mutex_Lock(&d->lock); |
165 | 0 | SOPC_Dict_Free_Fct* freeFct = SOPC_Dict_GetKeyFreeFunc(d->dict); |
166 | 0 | SOPC_Mutex_Unlock(&d->lock); |
167 | 0 | return freeFct; |
168 | 0 | } |
169 | | |
170 | | void SOPC_TSafe_Dict_SetKeyFreeFunc(SOPC_TSafe_Dict* d, SOPC_Dict_Free_Fct* func) |
171 | 0 | { |
172 | 0 | SOPC_ASSERT(NULL != d); |
173 | 0 | SOPC_Mutex_Lock(&d->lock); |
174 | 0 | SOPC_Dict_SetKeyFreeFunc(d->dict, func); |
175 | 0 | SOPC_Mutex_Unlock(&d->lock); |
176 | 0 | } |
177 | | |
178 | | SOPC_Dict_Free_Fct* SOPC_TSafe_Dict_GetValueFreeFunc(SOPC_TSafe_Dict* d) |
179 | 0 | { |
180 | 0 | if (NULL == d) |
181 | 0 | { |
182 | 0 | return NULL; |
183 | 0 | } |
184 | 0 | SOPC_Mutex_Lock(&d->lock); |
185 | 0 | SOPC_Dict_Free_Fct* func = SOPC_Dict_GetValueFreeFunc(d->dict); |
186 | 0 | SOPC_Mutex_Unlock(&d->lock); |
187 | 0 | return func; |
188 | 0 | } |
189 | | |
190 | | void SOPC_TSafe_Dict_SetValueFreeFunc(SOPC_TSafe_Dict* d, SOPC_Dict_Free_Fct* func) |
191 | 0 | { |
192 | 0 | SOPC_ASSERT(NULL != d); |
193 | 0 | SOPC_Mutex_Lock(&d->lock); |
194 | 0 | SOPC_Dict_SetValueFreeFunc(d->dict, func); |
195 | 0 | SOPC_Mutex_Unlock(&d->lock); |
196 | 0 | } |
197 | | |
198 | | size_t SOPC_TSafe_Dict_Size(SOPC_TSafe_Dict* d) |
199 | 0 | { |
200 | 0 | if (NULL == d) |
201 | 0 | { |
202 | 0 | return 0; |
203 | 0 | } |
204 | 0 | SOPC_Mutex_Lock(&d->lock); |
205 | 0 | size_t s = SOPC_Dict_Size(d->dict); |
206 | 0 | SOPC_Mutex_Unlock(&d->lock); |
207 | 0 | return s; |
208 | 0 | } |
209 | | |
210 | | size_t SOPC_TSafe_Dict_Capacity(SOPC_TSafe_Dict* d) |
211 | 0 | { |
212 | 0 | if (NULL == d) |
213 | 0 | { |
214 | 0 | return 0; |
215 | 0 | } |
216 | 0 | SOPC_Mutex_Lock(&d->lock); |
217 | 0 | size_t s = SOPC_Dict_Capacity(d->dict); |
218 | 0 | SOPC_Mutex_Unlock(&d->lock); |
219 | 0 | return s; |
220 | 0 | } |
221 | | |
222 | | void SOPC_TSafe_Dict_ForEach(SOPC_TSafe_Dict* d, SOPC_Dict_ForEach_Fct* func, uintptr_t user_data) |
223 | 0 | { |
224 | 0 | SOPC_ASSERT(NULL != d); |
225 | 0 | SOPC_Mutex_Lock(&d->lock); |
226 | 0 | SOPC_Dict_ForEach(d->dict, func, user_data); |
227 | 0 | SOPC_Mutex_Unlock(&d->lock); |
228 | 0 | } |