1 /*
2 +----------------------------------------------------------------------+
3 | Zend Engine |
4 +----------------------------------------------------------------------+
5 | Copyright (c) Zend Technologies Ltd. (http://www.zend.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 2.00 of the Zend license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.zend.com/license/2_00.txt. |
11 | If you did not receive a copy of the Zend license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@zend.com so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Authors: Harald Radi <harald.radi@nme.at> |
16 +----------------------------------------------------------------------+
17 */
18
19 #include "zend.h"
20 #include "zend_ts_hash.h"
21
22 /* ts management functions */
begin_read(TsHashTable * ht)23 static void begin_read(TsHashTable *ht)
24 {
25 #ifdef ZTS
26 tsrm_mutex_lock(ht->mx_reader);
27 if ((++(ht->reader)) == 1) {
28 tsrm_mutex_lock(ht->mx_writer);
29 }
30 tsrm_mutex_unlock(ht->mx_reader);
31 #endif
32 }
33
end_read(TsHashTable * ht)34 static void end_read(TsHashTable *ht)
35 {
36 #ifdef ZTS
37 tsrm_mutex_lock(ht->mx_reader);
38 if ((--(ht->reader)) == 0) {
39 tsrm_mutex_unlock(ht->mx_writer);
40 }
41 tsrm_mutex_unlock(ht->mx_reader);
42 #endif
43 }
44
begin_write(TsHashTable * ht)45 static void begin_write(TsHashTable *ht)
46 {
47 #ifdef ZTS
48 tsrm_mutex_lock(ht->mx_writer);
49 #endif
50 }
51
end_write(TsHashTable * ht)52 static void end_write(TsHashTable *ht)
53 {
54 #ifdef ZTS
55 tsrm_mutex_unlock(ht->mx_writer);
56 #endif
57 }
58
59 /* delegates */
zend_ts_hash_init(TsHashTable * ht,uint32_t nSize,dtor_func_t pDestructor,zend_bool persistent)60 ZEND_API void zend_ts_hash_init(TsHashTable *ht, uint32_t nSize, dtor_func_t pDestructor, zend_bool persistent)
61 {
62 #ifdef ZTS
63 ht->mx_reader = tsrm_mutex_alloc();
64 ht->mx_writer = tsrm_mutex_alloc();
65 ht->reader = 0;
66 #endif
67 _zend_hash_init(TS_HASH(ht), nSize, pDestructor, persistent);
68 }
69
zend_ts_hash_destroy(TsHashTable * ht)70 ZEND_API void zend_ts_hash_destroy(TsHashTable *ht)
71 {
72 begin_write(ht);
73 zend_hash_destroy(TS_HASH(ht));
74 end_write(ht);
75
76 #ifdef ZTS
77 tsrm_mutex_free(ht->mx_reader);
78 tsrm_mutex_free(ht->mx_writer);
79 #endif
80 }
81
zend_ts_hash_clean(TsHashTable * ht)82 ZEND_API void zend_ts_hash_clean(TsHashTable *ht)
83 {
84 ht->reader = 0;
85 begin_write(ht);
86 zend_hash_clean(TS_HASH(ht));
87 end_write(ht);
88 }
89
zend_ts_hash_add(TsHashTable * ht,zend_string * key,zval * pData)90 ZEND_API zval *zend_ts_hash_add(TsHashTable *ht, zend_string *key, zval *pData)
91 {
92 zval *retval;
93
94 begin_write(ht);
95 retval = zend_hash_add(TS_HASH(ht), key, pData);
96 end_write(ht);
97
98 return retval;
99 }
100
zend_ts_hash_update(TsHashTable * ht,zend_string * key,zval * pData)101 ZEND_API zval *zend_ts_hash_update(TsHashTable *ht, zend_string *key, zval *pData)
102 {
103 zval *retval;
104
105 begin_write(ht);
106 retval = zend_hash_update(TS_HASH(ht), key, pData);
107 end_write(ht);
108
109 return retval;
110 }
111
zend_ts_hash_next_index_insert(TsHashTable * ht,zval * pData)112 ZEND_API zval *zend_ts_hash_next_index_insert(TsHashTable *ht, zval *pData)
113 {
114 zval *retval;
115
116 begin_write(ht);
117 retval = zend_hash_next_index_insert(TS_HASH(ht), pData);
118 end_write(ht);
119
120 return retval;
121 }
122
zend_ts_hash_index_update(TsHashTable * ht,zend_ulong h,zval * pData)123 ZEND_API zval *zend_ts_hash_index_update(TsHashTable *ht, zend_ulong h, zval *pData)
124 {
125 zval *retval;
126
127 begin_write(ht);
128 retval = zend_hash_index_update(TS_HASH(ht), h, pData);
129 end_write(ht);
130
131 return retval;
132 }
133
zend_ts_hash_add_empty_element(TsHashTable * ht,zend_string * key)134 ZEND_API zval *zend_ts_hash_add_empty_element(TsHashTable *ht, zend_string *key)
135 {
136 zval *retval;
137
138 begin_write(ht);
139 retval = zend_hash_add_empty_element(TS_HASH(ht), key);
140 end_write(ht);
141
142 return retval;
143 }
144
zend_ts_hash_graceful_destroy(TsHashTable * ht)145 ZEND_API void zend_ts_hash_graceful_destroy(TsHashTable *ht)
146 {
147 begin_write(ht);
148 zend_hash_graceful_destroy(TS_HASH(ht));
149 end_write(ht);
150
151 #ifdef ZTS
152 tsrm_mutex_free(ht->mx_reader);
153 tsrm_mutex_free(ht->mx_writer);
154 #endif
155 }
156
zend_ts_hash_apply(TsHashTable * ht,apply_func_t apply_func)157 ZEND_API void zend_ts_hash_apply(TsHashTable *ht, apply_func_t apply_func)
158 {
159 begin_write(ht);
160 zend_hash_apply(TS_HASH(ht), apply_func);
161 end_write(ht);
162 }
163
zend_ts_hash_apply_with_argument(TsHashTable * ht,apply_func_arg_t apply_func,void * argument)164 ZEND_API void zend_ts_hash_apply_with_argument(TsHashTable *ht, apply_func_arg_t apply_func, void *argument)
165 {
166 begin_write(ht);
167 zend_hash_apply_with_argument(TS_HASH(ht), apply_func, argument);
168 end_write(ht);
169 }
170
zend_ts_hash_apply_with_arguments(TsHashTable * ht,apply_func_args_t apply_func,int num_args,...)171 ZEND_API void zend_ts_hash_apply_with_arguments(TsHashTable *ht, apply_func_args_t apply_func, int num_args, ...)
172 {
173 va_list args;
174
175 va_start(args, num_args);
176 begin_write(ht);
177 zend_hash_apply_with_arguments(TS_HASH(ht), apply_func, num_args, args);
178 end_write(ht);
179 va_end(args);
180 }
181
zend_ts_hash_reverse_apply(TsHashTable * ht,apply_func_t apply_func)182 ZEND_API void zend_ts_hash_reverse_apply(TsHashTable *ht, apply_func_t apply_func)
183 {
184 begin_write(ht);
185 zend_hash_reverse_apply(TS_HASH(ht), apply_func);
186 end_write(ht);
187 }
188
zend_ts_hash_del(TsHashTable * ht,zend_string * key)189 ZEND_API zend_result zend_ts_hash_del(TsHashTable *ht, zend_string *key)
190 {
191 zend_result retval;
192
193 begin_write(ht);
194 retval = zend_hash_del(TS_HASH(ht), key);
195 end_write(ht);
196
197 return retval;
198 }
199
zend_ts_hash_index_del(TsHashTable * ht,zend_ulong h)200 ZEND_API zend_result zend_ts_hash_index_del(TsHashTable *ht, zend_ulong h)
201 {
202 zend_result retval;
203
204 begin_write(ht);
205 retval = zend_hash_index_del(TS_HASH(ht), h);
206 end_write(ht);
207
208 return retval;
209 }
210
zend_ts_hash_find(TsHashTable * ht,zend_string * key)211 ZEND_API zval *zend_ts_hash_find(TsHashTable *ht, zend_string *key)
212 {
213 zval *retval;
214
215 begin_read(ht);
216 retval = zend_hash_find(TS_HASH(ht), key);
217 end_read(ht);
218
219 return retval;
220 }
221
zend_ts_hash_index_find(TsHashTable * ht,zend_ulong h)222 ZEND_API zval *zend_ts_hash_index_find(TsHashTable *ht, zend_ulong h)
223 {
224 zval *retval;
225
226 begin_read(ht);
227 retval = zend_hash_index_find(TS_HASH(ht), h);
228 end_read(ht);
229
230 return retval;
231 }
232
zend_ts_hash_copy(TsHashTable * target,TsHashTable * source,copy_ctor_func_t pCopyConstructor)233 ZEND_API void zend_ts_hash_copy(TsHashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor)
234 {
235 begin_read(source);
236 begin_write(target);
237 zend_hash_copy(TS_HASH(target), TS_HASH(source), pCopyConstructor);
238 end_write(target);
239 end_read(source);
240 }
241
zend_ts_hash_copy_to_hash(HashTable * target,TsHashTable * source,copy_ctor_func_t pCopyConstructor)242 ZEND_API void zend_ts_hash_copy_to_hash(HashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor)
243 {
244 begin_read(source);
245 zend_hash_copy(target, TS_HASH(source), pCopyConstructor);
246 end_read(source);
247 }
248
zend_ts_hash_merge(TsHashTable * target,TsHashTable * source,copy_ctor_func_t pCopyConstructor,bool overwrite)249 ZEND_API void zend_ts_hash_merge(TsHashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor, bool overwrite)
250 {
251 begin_read(source);
252 begin_write(target);
253 zend_hash_merge(TS_HASH(target), TS_HASH(source), pCopyConstructor, overwrite);
254 end_write(target);
255 end_read(source);
256 }
257
zend_ts_hash_merge_ex(TsHashTable * target,TsHashTable * source,copy_ctor_func_t pCopyConstructor,merge_checker_func_t pMergeSource,void * pParam)258 ZEND_API void zend_ts_hash_merge_ex(TsHashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor, merge_checker_func_t pMergeSource, void *pParam)
259 {
260 begin_read(source);
261 begin_write(target);
262 zend_hash_merge_ex(TS_HASH(target), TS_HASH(source), pCopyConstructor, pMergeSource, pParam);
263 end_write(target);
264 end_read(source);
265 }
266
zend_ts_hash_sort(TsHashTable * ht,sort_func_t sort_func,bucket_compare_func_t compare_func,bool renumber)267 ZEND_API void zend_ts_hash_sort(TsHashTable *ht, sort_func_t sort_func, bucket_compare_func_t compare_func, bool renumber)
268 {
269 begin_write(ht);
270 zend_hash_sort_ex(TS_HASH(ht), sort_func, compare_func, renumber);
271 end_write(ht);
272 }
273
zend_ts_hash_compare(TsHashTable * ht1,TsHashTable * ht2,compare_func_t compar,zend_bool ordered)274 ZEND_API int zend_ts_hash_compare(TsHashTable *ht1, TsHashTable *ht2, compare_func_t compar, zend_bool ordered)
275 {
276 int retval;
277
278 begin_read(ht1);
279 begin_read(ht2);
280 retval = zend_hash_compare(TS_HASH(ht1), TS_HASH(ht2), compar, ordered);
281 end_read(ht2);
282 end_read(ht1);
283
284 return retval;
285 }
286
zend_ts_hash_minmax(TsHashTable * ht,bucket_compare_func_t compar,int flag)287 ZEND_API zval *zend_ts_hash_minmax(TsHashTable *ht, bucket_compare_func_t compar, int flag)
288 {
289 zval *retval;
290
291 begin_read(ht);
292 retval = zend_hash_minmax(TS_HASH(ht), compar, flag);
293 end_read(ht);
294
295 return retval;
296 }
297
zend_ts_hash_num_elements(TsHashTable * ht)298 ZEND_API int zend_ts_hash_num_elements(TsHashTable *ht)
299 {
300 int retval;
301
302 begin_read(ht);
303 retval = zend_hash_num_elements(TS_HASH(ht));
304 end_read(ht);
305
306 return retval;
307 }
308
zend_ts_hash_rehash(TsHashTable * ht)309 ZEND_API void zend_ts_hash_rehash(TsHashTable *ht)
310 {
311 begin_write(ht);
312 zend_hash_rehash(TS_HASH(ht));
313 end_write(ht);
314 }
315
zend_ts_hash_str_find(TsHashTable * ht,const char * key,size_t len)316 ZEND_API zval *zend_ts_hash_str_find(TsHashTable *ht, const char *key, size_t len)
317 {
318 zval *retval;
319
320 begin_read(ht);
321 retval = zend_hash_str_find(TS_HASH(ht), key, len);
322 end_read(ht);
323
324 return retval;
325 }
326
zend_ts_hash_str_update(TsHashTable * ht,const char * key,size_t len,zval * pData)327 ZEND_API zval *zend_ts_hash_str_update(TsHashTable *ht, const char *key, size_t len, zval *pData)
328 {
329 zval *retval;
330
331 begin_write(ht);
332 retval = zend_hash_str_update(TS_HASH(ht), key, len, pData);
333 end_write(ht);
334
335 return retval;
336 }
337
zend_ts_hash_str_add(TsHashTable * ht,const char * key,size_t len,zval * pData)338 ZEND_API zval *zend_ts_hash_str_add(TsHashTable *ht, const char *key, size_t len, zval *pData)
339 {
340 zval *retval;
341
342 begin_write(ht);
343 retval = zend_hash_str_add(TS_HASH(ht), key, len, pData);
344 end_write(ht);
345
346 return retval;
347 }
348