xref: /PHP-8.0/Zend/zend_ts_hash.c (revision fa8d9b11)
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