2 +--------------------------------------------------------------------+
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 +--------------------------------------------------------------------+
13 #ifndef PHP_RAPHF_API_H
14 #define PHP_RAPHF_API_H
16 #include "php_raphf.h"
19 * A resource constructor.
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
25 typedef void *(*php_resource_factory_handle_ctor_t
)(void *opaque
, void *init_arg
);
28 * The copy constructor of a resource.
30 * @param opaque the factory's data
31 * @param handle the (persistent) handle to copy
33 typedef void *(*php_resource_factory_handle_copy_t
)(void *opaque
, void *handle
);
36 * The destructor of a resource.
38 * @param opaque the factory's data
39 * @param handle the handle to destroy
41 typedef void (*php_resource_factory_handle_dtor_t
)(void *opaque
, void *handle
);
44 * The resource ops consisting of a ctor, a copy ctor and a dtor.
46 * Define this ops and register them with php_persistent_handle_provide()
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
;
59 * The resource factory.
61 typedef struct php_resource_factory
{
62 /** The resource ops */
63 php_resource_factory_ops_t fops
;
64 /** Opaque user data */
66 /** User data destructor */
67 void (*dtor
)(void *data
);
68 /** How often this factory is referenced */
70 } php_resource_factory_t
;
73 * Initialize a resource factory.
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.
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
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
));
91 * Increase the refcount of the resource factory.
93 * @param rf the resource factory
94 * @return the new refcount
96 PHP_RAPHF_API
unsigned php_resource_factory_addref(php_resource_factory_t
*rf
);
99 * Destroy the resource factory.
101 * If the factory's refcount reaches 0, the \a dtor for \a data is called.
103 * @param f the resource factory
105 PHP_RAPHF_API
void php_resource_factory_dtor(php_resource_factory_t
*f
);
108 * Destroy and free the resource factory.
110 * Calls php_resource_factory_dtor() and frees \a f if the factory's refcount
113 * @param f the resource factory
115 PHP_RAPHF_API
void php_resource_factory_free(php_resource_factory_t
**f
);
118 * Construct a resource by the resource factory \a f
120 * @param f the resource factory
121 * @param init_arg for the resource constructor
122 * @return the new resource
124 PHP_RAPHF_API
void *php_resource_factory_handle_ctor(php_resource_factory_t
*f
,
128 * Create a copy of the resource \a handle
130 * @param f the resource factory
131 * @param handle the resource to copy
134 PHP_RAPHF_API
void *php_resource_factory_handle_copy(php_resource_factory_t
*f
,
138 * Destroy (and free) the resource
140 * @param f the resource factory
141 * @param handle the resource to destroy
143 PHP_RAPHF_API
void php_resource_factory_handle_dtor(php_resource_factory_t
*f
,
147 * Persistent handles storage
149 typedef struct php_persistent_handle_list
{
150 /** Storage of free resources */
152 /** Count of acquired resources */
154 } php_persistent_handle_list_t
;
157 * Definition of a persistent handle provider.
158 * Holds a resource factory an a persistent handle list.
160 typedef struct php_persistent_handle_provider
{
162 * The list of free handles.
163 * Hash of "ident" => array(handles) entries. Persistent handles are
164 * acquired out of this list.
166 php_persistent_handle_list_t list
;
169 * The resource factory.
170 * New handles are created by this factory.
172 php_resource_factory_t rf
;
173 } php_persistent_handle_provider_t
;
175 typedef struct php_persistent_handle_factory php_persistent_handle_factory_t
;
178 * Wakeup the persistent handle on re-acquisition.
180 typedef void (*php_persistent_handle_wakeup_t
)(
181 php_persistent_handle_factory_t
*f
, void **handle
);
183 * Retire the persistent handle on release.
185 typedef void (*php_persistent_handle_retire_t
)(
186 php_persistent_handle_factory_t
*f
, void **handle
);
189 * Definition of a persistent handle factory.
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().
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
;
203 /** The ident for which this factory manages resources */
206 /** Whether it has to be free'd on php_persistent_handle_abandon() */
207 unsigned free_on_abandon
:1;
211 * Register a persistent handle provider in MINIT.
213 * Registers a factory provider for \a name_str with \a fops resource factory
214 * ops. Call this in your MINIT.
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
220 * A php_persistent_handle_factory can then be retrieved by
221 * php_persistent_handle_concede() at runtime.
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
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 *));
234 * Retrieve a persistent handle factory at runtime.
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.
240 * The wakeup routine \a wakeup and the retire routine \a retire will be
241 * assigned to the new php_persistent_handle_factory.
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
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
);
257 * Abandon the persistent handle factory.
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.
263 * @param a the persistent handle factory to destroy
265 PHP_RAPHF_API
void php_persistent_handle_abandon(
266 php_persistent_handle_factory_t
*a
);
269 * Acquire a persistent handle.
271 * That is, either re-use a resource from the free list or create a new handle.
273 * If a handle is acquired from the free list, the
274 * php_persistent_handle_factory::wakeup callback will be executed for that
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
281 PHP_RAPHF_API
void *php_persistent_handle_acquire(
282 php_persistent_handle_factory_t
*a
, void *init_arg
);
285 * Release a persistent handle.
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().
290 * If a handle is put back into the free list, the
291 * php_persistent_handle_factory::retire callback will be executed for that
294 * @param a the persistent handle factory
295 * @param handle the handle to release
297 PHP_RAPHF_API
void php_persistent_handle_release(
298 php_persistent_handle_factory_t
*a
, void *handle
);
301 * Copy a persistent handle.
303 * Let the underlying resource factory copy the \a handle.
305 * @param a the persistent handle factory
306 * @param handle the resource to accrete
308 PHP_RAPHF_API
void *php_persistent_handle_accrete(
309 php_persistent_handle_factory_t
*a
, void *handle
);
312 * Retrieve persistent handle resource factory ops.
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
321 * php_resource_factory_t *create_my_rf(zend_string *persistent_id)
323 * php_resource_factory_t *rf;
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);
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);
335 * rf = php_resource_factory_init(NULL, &myops, NULL, NULL);
341 PHP_RAPHF_API php_resource_factory_ops_t
*
342 php_persistent_handle_get_resource_factory_ops(void);
345 * Create a resource factory for persistent handles.
347 * This will create a resource factory with persistent handle ops, which wraps
348 * the provided reource factory \a pf.
350 * @param a the persistent handle resource factory to initialize
351 * @param pf the resource factory to wrap
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
);
358 * Check whether a resource factory is a persistent handle resource factory.
360 * @param a the resource factory to check
362 PHP_RAPHF_API zend_bool
php_resource_factory_is_persistent(
363 php_resource_factory_t
*a
);
366 * Clean persistent handles up.
368 * Destroy persistent handles of provider \a name and in subsidiary
369 * namespace \a ident.
371 * If \a name is NULL, all persistent handles of all providers with a
372 * matching \a ident will be cleaned up.
374 * If \a identr is NULL all persistent handles of the provider will be
377 * Ergo, if both, \a name and \a ident are NULL, then all
378 * persistent handles will be cleaned up.
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.
384 * @param name the provider name; may be NULL
385 * @param ident the subsidiary namespace name; may be NULL
387 PHP_RAPHF_API
void php_persistent_handle_cleanup(zend_string
*name
,
391 * Retrieve statistics about the current process/thread's persistent handles.
393 * @return a HashTable like:
405 PHP_RAPHF_API HashTable
*php_persistent_handle_statall(HashTable
*ht
);
407 #endif /* PHP_RAPHF_API_H */
415 * vim600: noet sw=4 ts=4 fdm=marker
416 * vim<600: noet sw=4 ts=4