e9f0581abf9e65dd851f1cf43b7de78c5d4c2b7d
[m6w6/ext-raphf] / src / php_raphf_api.h
1 /*
2 +--------------------------------------------------------------------+
3 | PECL :: raphf |
4 +--------------------------------------------------------------------+
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted provided that the conditions mentioned |
7 | in the accompanying LICENSE file are met. |
8 +--------------------------------------------------------------------+
9 | Copyright (c) 2013, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
11 */
12
13 #ifndef PHP_RAPHF_API_H
14 #define PHP_RAPHF_API_H
15
16 #include "php_raphf.h"
17
18 /**
19 * A resource constructor.
20 *
21 * @param opaque is the \a data from php_persistent_handle_provide()
22 * @param init_arg is the \a init_arg from php_resource_factory_init()
23 * @return the created (persistent) handle
24 */
25 typedef void *(*php_resource_factory_handle_ctor_t)(void *opaque, void *init_arg);
26
27 /**
28 * The copy constructor of a resource.
29 *
30 * @param opaque the factory's data
31 * @param handle the (persistent) handle to copy
32 */
33 typedef void *(*php_resource_factory_handle_copy_t)(void *opaque, void *handle);
34
35 /**
36 * The destructor of a resource.
37 *
38 * @param opaque the factory's data
39 * @param handle the handle to destroy
40 */
41 typedef void (*php_resource_factory_handle_dtor_t)(void *opaque, void *handle);
42
43 /**
44 * The resource ops consisting of a ctor, a copy ctor and a dtor.
45 *
46 * Define this ops and register them with php_persistent_handle_provide()
47 * in MINIT.
48 */
49 typedef struct php_resource_factory_ops {
50 /** The resource constructor */
51 php_resource_factory_handle_ctor_t ctor;
52 /** The resource's copy constructor */
53 php_resource_factory_handle_copy_t copy;
54 /** The resource's destructor */
55 php_resource_factory_handle_dtor_t dtor;
56 } php_resource_factory_ops_t;
57
58 /**
59 * The resource factory.
60 */
61 typedef struct php_resource_factory {
62 /** The resource ops */
63 php_resource_factory_ops_t fops;
64 /** Opaque user data */
65 void *data;
66 /** User data destructor */
67 void (*dtor)(void *data);
68 /** How often this factory is referenced */
69 unsigned refcount;
70 } php_resource_factory_t;
71
72 /**
73 * Initialize a resource factory.
74 *
75 * If you register a \a dtor for a resource factory used with a persistent
76 * handle provider, be sure to call php_persistent_handle_cleanup() for your
77 * registered provider in MSHUTDOWN, else the dtor will point to no longer
78 * available memory if the extension has already been unloaded.
79 *
80 * @param f the factory to initialize; if NULL allocated on the heap
81 * @param fops the resource ops to assign to the factory
82 * @param data opaque user data; may be NULL
83 * @param dtor a destructor for the data; may be NULL
84 * @return \a f or an allocated resource factory
85 */
86 PHP_RAPHF_API php_resource_factory_t *php_resource_factory_init(
87 php_resource_factory_t *f, php_resource_factory_ops_t *fops, void *data,
88 void (*dtor)(void *data));
89
90 /**
91 * Increase the refcount of the resource factory.
92 *
93 * @param rf the resource factory
94 * @return the new refcount
95 */
96 PHP_RAPHF_API unsigned php_resource_factory_addref(php_resource_factory_t *rf);
97
98 /**
99 * Destroy the resource factory.
100 *
101 * If the factory's refcount reaches 0, the \a dtor for \a data is called.
102 *
103 * @param f the resource factory
104 */
105 PHP_RAPHF_API void php_resource_factory_dtor(php_resource_factory_t *f);
106
107 /**
108 * Destroy and free the resource factory.
109 *
110 * Calls php_resource_factory_dtor() and frees \a f if the factory's refcount
111 * reached 0.
112 *
113 * @param f the resource factory
114 */
115 PHP_RAPHF_API void php_resource_factory_free(php_resource_factory_t **f);
116
117 /**
118 * Construct a resource by the resource factory \a f
119 *
120 * @param f the resource factory
121 * @param init_arg for the resource constructor
122 * @return the new resource
123 */
124 PHP_RAPHF_API void *php_resource_factory_handle_ctor(php_resource_factory_t *f,
125 void *init_arg);
126
127 /**
128 * Create a copy of the resource \a handle
129 *
130 * @param f the resource factory
131 * @param handle the resource to copy
132 * @return the copy
133 */
134 PHP_RAPHF_API void *php_resource_factory_handle_copy(php_resource_factory_t *f,
135 void *handle);
136
137 /**
138 * Destroy (and free) the resource
139 *
140 * @param f the resource factory
141 * @param handle the resource to destroy
142 */
143 PHP_RAPHF_API void php_resource_factory_handle_dtor(php_resource_factory_t *f,
144 void *handle);
145
146 /**
147 * Persistent handles storage
148 */
149 typedef struct php_persistent_handle_list {
150 /** Storage of free resources */
151 HashTable free;
152 /** Count of acquired resources */
153 ulong used;
154 } php_persistent_handle_list_t;
155
156 /**
157 * Definition of a persistent handle provider.
158 * Holds a resource factory an a persistent handle list.
159 */
160 typedef struct php_persistent_handle_provider {
161 /**
162 * The list of free handles.
163 * Hash of "ident" => array(handles) entries. Persistent handles are
164 * acquired out of this list.
165 */
166 php_persistent_handle_list_t list;
167
168 /**
169 * The resource factory.
170 * New handles are created by this factory.
171 */
172 php_resource_factory_t rf;
173 } php_persistent_handle_provider_t;
174
175 typedef struct php_persistent_handle_factory php_persistent_handle_factory_t;
176
177 /**
178 * Wakeup the persistent handle on re-acquisition.
179 */
180 typedef void (*php_persistent_handle_wakeup_t)(
181 php_persistent_handle_factory_t *f, void **handle);
182 /**
183 * Retire the persistent handle on release.
184 */
185 typedef void (*php_persistent_handle_retire_t)(
186 php_persistent_handle_factory_t *f, void **handle);
187
188 /**
189 * Definition of a persistent handle factory.
190 *
191 * php_persistent_handle_concede() will return a pointer to a
192 * php_persistent_handle_factory if a provider for the \a name has
193 * been registered with php_persistent_handle_provide().
194 */
195 struct php_persistent_handle_factory {
196 /** The persistent handle provider */
197 php_persistent_handle_provider_t *provider;
198 /** The persistent handle wakeup routine; may be NULL */
199 php_persistent_handle_wakeup_t wakeup;
200 /** The persistent handle retire routine; may be NULL */
201 php_persistent_handle_retire_t retire;
202
203 /** The ident for which this factory manages resources */
204 zend_string *ident;
205
206 /** Whether it has to be free'd on php_persistent_handle_abandon() */
207 unsigned free_on_abandon:1;
208 };
209
210 /**
211 * Register a persistent handle provider in MINIT.
212 *
213 * Registers a factory provider for \a name_str with \a fops resource factory
214 * ops. Call this in your MINIT.
215 *
216 * A php_resource_factory will be created with \a fops, \a data and \a dtor
217 * and will be stored together with a php_persistent_handle_list in the global
218 * raphf hash.
219 *
220 * A php_persistent_handle_factory can then be retrieved by
221 * php_persistent_handle_concede() at runtime.
222 *
223 * @param name the provider name, e.g. "http\Client\Curl"
224 * @param fops the resource factory ops
225 * @param data opaque user data
226 * @param dtor \a data destructor
227 * @return SUCCESS/FAILURE
228 */
229 PHP_RAPHF_API ZEND_RESULT_CODE php_persistent_handle_provide(
230 zend_string *name, php_resource_factory_ops_t *fops,
231 void *data, void (*dtor)(void *));
232
233 /**
234 * Retrieve a persistent handle factory at runtime.
235 *
236 * If a persistent handle provider has been registered for \a name, a new
237 * php_persistent_handle_factory creating resources in the \a ident
238 * namespace will be constructed.
239 *
240 * The wakeup routine \a wakeup and the retire routine \a retire will be
241 * assigned to the new php_persistent_handle_factory.
242 *
243 * @param a pointer to a factory; allocated on the heap if NULL
244 * @param name the provider name, e.g. "http\Client\Curl"
245 * @param ident the subsidiary namespace, e.g. "php.net:80"
246 * @param wakeup any persistent handle wakeup routine
247 * @param retire any persistent handle retire routine
248 * @return \a a or an allocated persistent handle factory
249 */
250 PHP_RAPHF_API php_persistent_handle_factory_t *php_persistent_handle_concede(
251 php_persistent_handle_factory_t *a,
252 zend_string *name, zend_string *ident,
253 php_persistent_handle_wakeup_t wakeup,
254 php_persistent_handle_retire_t retire);
255
256 /**
257 * Abandon the persistent handle factory.
258 *
259 * Destroy a php_persistent_handle_factory created by
260 * php_persistent_handle_concede(). If the memory for the factory was allocated,
261 * it will automatically be free'd.
262 *
263 * @param a the persistent handle factory to destroy
264 */
265 PHP_RAPHF_API void php_persistent_handle_abandon(
266 php_persistent_handle_factory_t *a);
267
268 /**
269 * Acquire a persistent handle.
270 *
271 * That is, either re-use a resource from the free list or create a new handle.
272 *
273 * If a handle is acquired from the free list, the
274 * php_persistent_handle_factory::wakeup callback will be executed for that
275 * handle.
276 *
277 * @param a the persistent handle factory
278 * @param init_arg the \a init_arg for php_resource_factory_handle_ctor()
279 * @return the acquired resource
280 */
281 PHP_RAPHF_API void *php_persistent_handle_acquire(
282 php_persistent_handle_factory_t *a, void *init_arg);
283
284 /**
285 * Release a persistent handle.
286 *
287 * That is, either put it back into the free list for later re-use or clean it
288 * up with php_resource_factory_handle_dtor().
289 *
290 * If a handle is put back into the free list, the
291 * php_persistent_handle_factory::retire callback will be executed for that
292 * handle.
293 *
294 * @param a the persistent handle factory
295 * @param handle the handle to release
296 */
297 PHP_RAPHF_API void php_persistent_handle_release(
298 php_persistent_handle_factory_t *a, void *handle);
299
300 /**
301 * Copy a persistent handle.
302 *
303 * Let the underlying resource factory copy the \a handle.
304 *
305 * @param a the persistent handle factory
306 * @param handle the resource to accrete
307 */
308 PHP_RAPHF_API void *php_persistent_handle_accrete(
309 php_persistent_handle_factory_t *a, void *handle);
310
311 /**
312 * Retrieve persistent handle resource factory ops.
313 *
314 * These ops can be used to mask a persistent handle factory as
315 * resource factory itself, so you can transparently use the
316 * resource factory API, both for persistent and non-persistent
317 * ressources.
318 *
319 * Example:
320 * \code{.c}
321 * php_resource_factory_t *create_my_rf(zend_string *persistent_id)
322 * {
323 * php_resource_factory_t *rf;
324 *
325 * if (persistent_id) {
326 * php_persistent_handle_factory_t *pf;
327 * php_resource_factory_ops_t *ops;
328 * zend_string *ns = zend_string_init("my", 2, 1);
329 *
330 * ops = php_persistent_handle_get_resource_factory_ops();
331 * pf = php_persistent_handle_concede(NULL, ns, persistent_id, NULL, NULL);
332 * rf = php_persistent_handle_resource_factory_init(NULL, pf);
333 * zend_string_release(ns);
334 * } else {
335 * rf = php_resource_factory_init(NULL, &myops, NULL, NULL);
336 * }
337 * return rf;
338 * }
339 * \endcode
340 */
341 PHP_RAPHF_API php_resource_factory_ops_t *
342 php_persistent_handle_get_resource_factory_ops(void);
343
344 /**
345 * Create a resource factory for persistent handles.
346 *
347 * This will create a resource factory with persistent handle ops, which wraps
348 * the provided reource factory \a pf.
349 *
350 * @param a the persistent handle resource factory to initialize
351 * @param pf the resource factory to wrap
352 */
353 PHP_RAPHF_API php_resource_factory_t *
354 php_persistent_handle_resource_factory_init(php_resource_factory_t *a,
355 php_persistent_handle_factory_t *pf);
356
357 /**
358 * Check whether a resource factory is a persistent handle resource factory.
359 *
360 * @param a the resource factory to check
361 */
362 PHP_RAPHF_API zend_bool php_resource_factory_is_persistent(
363 php_resource_factory_t *a);
364
365 /**
366 * Clean persistent handles up.
367 *
368 * Destroy persistent handles of provider \a name and in subsidiary
369 * namespace \a ident.
370 *
371 * If \a name is NULL, all persistent handles of all providers with a
372 * matching \a ident will be cleaned up.
373 *
374 * If \a identr is NULL all persistent handles of the provider will be
375 * cleaned up.
376 *
377 * Ergo, if both, \a name and \a ident are NULL, then all
378 * persistent handles will be cleaned up.
379 *
380 * You must call this in MSHUTDOWN, if your resource factory ops hold a
381 * registered php_resource_factory::dtor, else the dtor will point to
382 * memory not any more available if the extension has already been unloaded.
383 *
384 * @param name the provider name; may be NULL
385 * @param ident the subsidiary namespace name; may be NULL
386 */
387 PHP_RAPHF_API void php_persistent_handle_cleanup(zend_string *name,
388 zend_string *ident);
389
390 /**
391 * Retrieve statistics about the current process/thread's persistent handles.
392 *
393 * @return a HashTable like:
394 * \code
395 * [
396 * "name" => [
397 * "ident" => [
398 * "used" => 1,
399 * "free" => 0,
400 * ]
401 * ]
402 * ]
403 * \endcode
404 */
405 PHP_RAPHF_API HashTable *php_persistent_handle_statall(HashTable *ht);
406
407 #endif /* PHP_RAPHF_API_H */
408
409
410 /*
411 * Local variables:
412 * tab-width: 4
413 * c-basic-offset: 4
414 * End:
415 * vim600: noet sw=4 ts=4 fdm=marker
416 * vim<600: noet sw=4 ts=4
417 */