xref: /PHP-5.6/Zend/zend_ts_hash.c (revision 3537e95d)
1 /*
2    +----------------------------------------------------------------------+
3    | Zend Engine                                                          |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1998-2016 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 /* $Id$ */
20 
21 #include "zend.h"
22 #include "zend_ts_hash.h"
23 
24 /* ts management functions */
begin_read(TsHashTable * ht)25 static void begin_read(TsHashTable *ht)
26 {
27 #ifdef ZTS
28 	tsrm_mutex_lock(ht->mx_reader);
29 	if ((++(ht->reader)) == 1) {
30 		tsrm_mutex_lock(ht->mx_writer);
31 	}
32 	tsrm_mutex_unlock(ht->mx_reader);
33 #endif
34 }
35 
end_read(TsHashTable * ht)36 static void end_read(TsHashTable *ht)
37 {
38 #ifdef ZTS
39 	tsrm_mutex_lock(ht->mx_reader);
40 	if ((--(ht->reader)) == 0) {
41 		tsrm_mutex_unlock(ht->mx_writer);
42 	}
43 	tsrm_mutex_unlock(ht->mx_reader);
44 #endif
45 }
46 
begin_write(TsHashTable * ht)47 static void begin_write(TsHashTable *ht)
48 {
49 #ifdef ZTS
50 	tsrm_mutex_lock(ht->mx_writer);
51 #endif
52 }
53 
end_write(TsHashTable * ht)54 static void end_write(TsHashTable *ht)
55 {
56 #ifdef ZTS
57 	tsrm_mutex_unlock(ht->mx_writer);
58 #endif
59 }
60 
61 /* delegates */
_zend_ts_hash_init(TsHashTable * ht,uint nSize,dtor_func_t pDestructor,zend_bool persistent ZEND_FILE_LINE_DC)62 ZEND_API int _zend_ts_hash_init(TsHashTable *ht, uint nSize, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC)
63 {
64 #ifdef ZTS
65 	ht->mx_reader = tsrm_mutex_alloc();
66 	ht->mx_writer = tsrm_mutex_alloc();
67 	ht->reader = 0;
68 #endif
69 	return _zend_hash_init(TS_HASH(ht), nSize, pDestructor, persistent ZEND_FILE_LINE_RELAY_CC);
70 }
71 
_zend_ts_hash_init_ex(TsHashTable * ht,uint nSize,dtor_func_t pDestructor,zend_bool persistent,zend_bool bApplyProtection ZEND_FILE_LINE_DC)72 ZEND_API int _zend_ts_hash_init_ex(TsHashTable *ht, uint nSize, dtor_func_t pDestructor, zend_bool persistent, zend_bool bApplyProtection ZEND_FILE_LINE_DC)
73 {
74 #ifdef ZTS
75 	ht->mx_reader = tsrm_mutex_alloc();
76 	ht->mx_writer = tsrm_mutex_alloc();
77 	ht->reader = 0;
78 #endif
79 	return _zend_hash_init_ex(TS_HASH(ht), nSize, pDestructor, persistent, bApplyProtection ZEND_FILE_LINE_RELAY_CC);
80 }
81 
zend_ts_hash_destroy(TsHashTable * ht)82 ZEND_API void zend_ts_hash_destroy(TsHashTable *ht)
83 {
84 	begin_write(ht);
85 	zend_hash_destroy(TS_HASH(ht));
86 	end_write(ht);
87 
88 #ifdef ZTS
89 	tsrm_mutex_free(ht->mx_reader);
90 	tsrm_mutex_free(ht->mx_writer);
91 #endif
92 }
93 
zend_ts_hash_clean(TsHashTable * ht)94 ZEND_API void zend_ts_hash_clean(TsHashTable *ht)
95 {
96 	ht->reader = 0;
97 	begin_write(ht);
98 	zend_hash_clean(TS_HASH(ht));
99 	end_write(ht);
100 }
101 
_zend_ts_hash_add_or_update(TsHashTable * ht,char * arKey,uint nKeyLength,void * pData,uint nDataSize,void ** pDest,int flag ZEND_FILE_LINE_DC)102 ZEND_API int _zend_ts_hash_add_or_update(TsHashTable *ht, char *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC)
103 {
104 	int retval;
105 
106 	begin_write(ht);
107 	retval = _zend_hash_add_or_update(TS_HASH(ht), arKey, nKeyLength, pData, nDataSize, pDest, flag ZEND_FILE_LINE_RELAY_CC);
108 	end_write(ht);
109 
110 	return retval;
111 }
112 
_zend_ts_hash_quick_add_or_update(TsHashTable * ht,char * arKey,uint nKeyLength,ulong h,void * pData,uint nDataSize,void ** pDest,int flag ZEND_FILE_LINE_DC)113 ZEND_API int _zend_ts_hash_quick_add_or_update(TsHashTable *ht, char *arKey, uint nKeyLength, ulong h, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC)
114 {
115 	int retval;
116 
117 	begin_write(ht);
118 	retval = _zend_hash_quick_add_or_update(TS_HASH(ht), arKey, nKeyLength, h, pData, nDataSize, pDest, flag ZEND_FILE_LINE_RELAY_CC);
119 	end_write(ht);
120 
121 	return retval;
122 }
123 
_zend_ts_hash_index_update_or_next_insert(TsHashTable * ht,ulong h,void * pData,uint nDataSize,void ** pDest,int flag ZEND_FILE_LINE_DC)124 ZEND_API int _zend_ts_hash_index_update_or_next_insert(TsHashTable *ht, ulong h, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC)
125 {
126 	int retval;
127 
128 	begin_write(ht);
129 	retval = _zend_hash_index_update_or_next_insert(TS_HASH(ht), h, pData, nDataSize, pDest, flag ZEND_FILE_LINE_RELAY_CC);
130 	end_write(ht);
131 
132 	return retval;
133 }
134 
zend_ts_hash_add_empty_element(TsHashTable * ht,char * arKey,uint nKeyLength)135 ZEND_API int zend_ts_hash_add_empty_element(TsHashTable *ht, char *arKey, uint nKeyLength)
136 {
137 	int retval;
138 
139 	begin_write(ht);
140 	retval = zend_hash_add_empty_element(TS_HASH(ht), arKey, nKeyLength);
141 	end_write(ht);
142 
143 	return retval;
144 }
145 
zend_ts_hash_graceful_destroy(TsHashTable * ht)146 ZEND_API void zend_ts_hash_graceful_destroy(TsHashTable *ht)
147 {
148 	begin_write(ht);
149 	zend_hash_graceful_destroy(TS_HASH(ht));
150 	end_write(ht);
151 
152 #ifdef ZTS
153 	tsrm_mutex_free(ht->mx_reader);
154 	tsrm_mutex_free(ht->mx_writer);
155 #endif
156 }
157 
zend_ts_hash_apply(TsHashTable * ht,apply_func_t apply_func TSRMLS_DC)158 ZEND_API void zend_ts_hash_apply(TsHashTable *ht, apply_func_t apply_func TSRMLS_DC)
159 {
160 	begin_write(ht);
161 	zend_hash_apply(TS_HASH(ht), apply_func TSRMLS_CC);
162 	end_write(ht);
163 }
164 
zend_ts_hash_apply_with_argument(TsHashTable * ht,apply_func_arg_t apply_func,void * argument TSRMLS_DC)165 ZEND_API void zend_ts_hash_apply_with_argument(TsHashTable *ht, apply_func_arg_t apply_func, void *argument TSRMLS_DC)
166 {
167 	begin_write(ht);
168 	zend_hash_apply_with_argument(TS_HASH(ht), apply_func, argument TSRMLS_CC);
169 	end_write(ht);
170 }
171 
zend_ts_hash_apply_with_arguments(TsHashTable * ht TSRMLS_DC,apply_func_args_t apply_func,int num_args,...)172 ZEND_API void zend_ts_hash_apply_with_arguments(TsHashTable *ht TSRMLS_DC, apply_func_args_t apply_func, int num_args, ...)
173 {
174 	va_list args;
175 
176 	va_start(args, num_args);
177 	begin_write(ht);
178 	zend_hash_apply_with_arguments(TS_HASH(ht) TSRMLS_CC, apply_func, num_args, args);
179 	end_write(ht);
180 	va_end(args);
181 }
182 
zend_ts_hash_reverse_apply(TsHashTable * ht,apply_func_t apply_func TSRMLS_DC)183 ZEND_API void zend_ts_hash_reverse_apply(TsHashTable *ht, apply_func_t apply_func TSRMLS_DC)
184 {
185 	begin_write(ht);
186 	zend_hash_reverse_apply(TS_HASH(ht), apply_func TSRMLS_CC);
187 	end_write(ht);
188 }
189 
zend_ts_hash_del_key_or_index(TsHashTable * ht,char * arKey,uint nKeyLength,ulong h,int flag)190 ZEND_API int zend_ts_hash_del_key_or_index(TsHashTable *ht, char *arKey, uint nKeyLength, ulong h, int flag)
191 {
192 	int retval;
193 
194 	begin_write(ht);
195 	retval = zend_hash_del_key_or_index(TS_HASH(ht), arKey, nKeyLength, h, flag);
196 	end_write(ht);
197 
198 	return retval;
199 }
200 
zend_ts_get_hash_value(TsHashTable * ht,char * arKey,uint nKeyLength)201 ZEND_API ulong zend_ts_get_hash_value(TsHashTable *ht, char *arKey, uint nKeyLength)
202 {
203 	ulong retval;
204 
205 	begin_read(ht);
206 	retval = zend_get_hash_value(arKey, nKeyLength);
207 	end_read(ht);
208 
209 	return retval;
210 }
211 
zend_ts_hash_find(TsHashTable * ht,char * arKey,uint nKeyLength,void ** pData)212 ZEND_API int zend_ts_hash_find(TsHashTable *ht, char *arKey, uint nKeyLength, void **pData)
213 {
214 	int retval;
215 
216 	begin_read(ht);
217 	retval = zend_hash_find(TS_HASH(ht), arKey, nKeyLength, pData);
218 	end_read(ht);
219 
220 	return retval;
221 }
222 
zend_ts_hash_quick_find(TsHashTable * ht,char * arKey,uint nKeyLength,ulong h,void ** pData)223 ZEND_API int zend_ts_hash_quick_find(TsHashTable *ht, char *arKey, uint nKeyLength, ulong h, void **pData)
224 {
225 	int retval;
226 
227 	begin_read(ht);
228 	retval = zend_hash_quick_find(TS_HASH(ht), arKey, nKeyLength, h, pData);
229 	end_read(ht);
230 
231 	return retval;
232 }
233 
zend_ts_hash_index_find(TsHashTable * ht,ulong h,void ** pData)234 ZEND_API int zend_ts_hash_index_find(TsHashTable *ht, ulong h, void **pData)
235 {
236 	int retval;
237 
238 	begin_read(ht);
239 	retval = zend_hash_index_find(TS_HASH(ht), h, pData);
240 	end_read(ht);
241 
242 	return retval;
243 }
244 
zend_ts_hash_exists(TsHashTable * ht,char * arKey,uint nKeyLength)245 ZEND_API int zend_ts_hash_exists(TsHashTable *ht, char *arKey, uint nKeyLength)
246 {
247 	int retval;
248 
249 	begin_read(ht);
250 	retval = zend_hash_exists(TS_HASH(ht), arKey, nKeyLength);
251 	end_read(ht);
252 
253 	return retval;
254 }
255 
zend_ts_hash_index_exists(TsHashTable * ht,ulong h)256 ZEND_API int zend_ts_hash_index_exists(TsHashTable *ht, ulong h)
257 {
258 	int retval;
259 
260 	begin_read(ht);
261 	retval = zend_hash_index_exists(TS_HASH(ht), h);
262 	end_read(ht);
263 
264 	return retval;
265 }
266 
zend_ts_hash_copy(TsHashTable * target,TsHashTable * source,copy_ctor_func_t pCopyConstructor,void * tmp,uint size)267 ZEND_API void zend_ts_hash_copy(TsHashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size)
268 {
269 	begin_read(source);
270 	begin_write(target);
271 	zend_hash_copy(TS_HASH(target), TS_HASH(source), pCopyConstructor, tmp, size);
272 	end_write(target);
273 	end_read(source);
274 }
275 
zend_ts_hash_copy_to_hash(HashTable * target,TsHashTable * source,copy_ctor_func_t pCopyConstructor,void * tmp,uint size)276 ZEND_API void zend_ts_hash_copy_to_hash(HashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size)
277 {
278 	begin_read(source);
279 	zend_hash_copy(target, TS_HASH(source), pCopyConstructor, tmp, size);
280 	end_read(source);
281 }
282 
zend_ts_hash_merge(TsHashTable * target,TsHashTable * source,copy_ctor_func_t pCopyConstructor,void * tmp,uint size,int overwrite)283 ZEND_API void zend_ts_hash_merge(TsHashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size, int overwrite)
284 {
285 	begin_read(source);
286 	begin_write(target);
287 	zend_hash_merge(TS_HASH(target), TS_HASH(source), pCopyConstructor, tmp, size, overwrite);
288 	end_write(target);
289 	end_read(source);
290 }
291 
zend_ts_hash_merge_ex(TsHashTable * target,TsHashTable * source,copy_ctor_func_t pCopyConstructor,uint size,merge_checker_func_t pMergeSource,void * pParam)292 ZEND_API void zend_ts_hash_merge_ex(TsHashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor, uint size, merge_checker_func_t pMergeSource, void *pParam)
293 {
294 	begin_read(source);
295 	begin_write(target);
296 	zend_hash_merge_ex(TS_HASH(target), TS_HASH(source), pCopyConstructor, size, pMergeSource, pParam);
297 	end_write(target);
298 	end_read(source);
299 }
300 
zend_ts_hash_sort(TsHashTable * ht,sort_func_t sort_func,compare_func_t compare_func,int renumber TSRMLS_DC)301 ZEND_API int zend_ts_hash_sort(TsHashTable *ht, sort_func_t sort_func, compare_func_t compare_func, int renumber TSRMLS_DC)
302 {
303 	int retval;
304 
305 	begin_write(ht);
306 	retval = zend_hash_sort(TS_HASH(ht), sort_func, compare_func, renumber TSRMLS_CC);
307 	end_write(ht);
308 
309 	return retval;
310 }
311 
zend_ts_hash_compare(TsHashTable * ht1,TsHashTable * ht2,compare_func_t compar,zend_bool ordered TSRMLS_DC)312 ZEND_API int zend_ts_hash_compare(TsHashTable *ht1, TsHashTable *ht2, compare_func_t compar, zend_bool ordered TSRMLS_DC)
313 {
314 	int retval;
315 
316 	begin_read(ht1);
317 	begin_read(ht2);
318 	retval = zend_hash_compare(TS_HASH(ht1), TS_HASH(ht2), compar, ordered TSRMLS_CC);
319 	end_read(ht2);
320 	end_read(ht1);
321 
322 	return retval;
323 }
324 
zend_ts_hash_minmax(TsHashTable * ht,compare_func_t compar,int flag,void ** pData TSRMLS_DC)325 ZEND_API int zend_ts_hash_minmax(TsHashTable *ht, compare_func_t compar, int flag, void **pData TSRMLS_DC)
326 {
327 	int retval;
328 
329 	begin_read(ht);
330 	retval = zend_hash_minmax(TS_HASH(ht), compar, flag, pData TSRMLS_CC);
331 	end_read(ht);
332 
333 	return retval;
334 }
335 
zend_ts_hash_num_elements(TsHashTable * ht)336 ZEND_API int zend_ts_hash_num_elements(TsHashTable *ht)
337 {
338 	int retval;
339 
340 	begin_read(ht);
341 	retval = zend_hash_num_elements(TS_HASH(ht));
342 	end_read(ht);
343 
344 	return retval;
345 }
346 
zend_ts_hash_rehash(TsHashTable * ht)347 ZEND_API int zend_ts_hash_rehash(TsHashTable *ht)
348 {
349 	int retval;
350 
351 	begin_write(ht);
352 	retval = zend_hash_rehash(TS_HASH(ht));
353 	end_write(ht);
354 
355 	return retval;
356 }
357 
358 #if ZEND_DEBUG
zend_ts_hash_display_pListTail(TsHashTable * ht)359 void zend_ts_hash_display_pListTail(TsHashTable *ht)
360 {
361 	begin_read(ht);
362 	zend_hash_display_pListTail(TS_HASH(ht));
363 	end_read(ht);
364 }
365 
zend_ts_hash_display(TsHashTable * ht)366 void zend_ts_hash_display(TsHashTable *ht)
367 {
368 	begin_read(ht);
369 	zend_hash_display(TS_HASH(ht));
370 	end_read(ht);
371 }
372 #endif
373 
374 /*
375  * Local variables:
376  * tab-width: 4
377  * c-basic-offset: 4
378  * indent-tabs-mode: t
379  * End:
380  */
381