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 +--------------------------------------------------------------------+
18 extern zend_module_entry raphf_module_entry
;
19 #define phpext_raphf_ptr &raphf_module_entry
21 #define PHP_RAPHF_VERSION "2.0.0dev"
24 # define PHP_RAPHF_API __declspec(dllexport)
25 #elif defined(__GNUC__) && __GNUC__ >= 4
26 # define PHP_RAPHF_API extern __attribute__ ((visibility("default")))
28 # define PHP_RAPHF_API extern
38 * A resource constructor.
40 * @param opaque is the \a data from php_persistent_handle_provide()
41 * @param init_arg is the \a init_arg from php_resource_factory_init()
42 * @return the created (persistent) handle
44 typedef void *(*php_resource_factory_handle_ctor_t
)(void *opaque
, void *init_arg
);
47 * The copy constructor of a resource.
49 * @param opaque the factory's data
50 * @param handle the (persistent) handle to copy
52 typedef void *(*php_resource_factory_handle_copy_t
)(void *opaque
, void *handle
);
55 * The destructor of a resource.
57 * @param opaque the factory's data
58 * @param handle the handle to destroy
60 typedef void (*php_resource_factory_handle_dtor_t
)(void *opaque
, void *handle
);
63 * The resource ops consisting of a ctor, a copy ctor and a dtor.
65 * Define this ops and register them with php_persistent_handle_provide()
68 typedef struct php_resource_factory_ops
{
69 /** The resource constructor */
70 php_resource_factory_handle_ctor_t ctor
;
71 /** The resource's copy constructor */
72 php_resource_factory_handle_copy_t copy
;
73 /** The resource's destructor */
74 php_resource_factory_handle_dtor_t dtor
;
75 } php_resource_factory_ops_t
;
78 * The resource factory.
80 typedef struct php_resource_factory
{
81 /** The resource ops */
82 php_resource_factory_ops_t fops
;
83 /** Opaque user data */
85 /** User data destructor */
86 void (*dtor
)(void *data
);
87 /** How often this factory is referenced */
89 } php_resource_factory_t
;
92 * Initialize a resource factory.
94 * If you register a \a dtor for a resource factory used with a persistent
95 * handle provider, be sure to call php_persistent_handle_cleanup() for your
96 * registered provider in MSHUTDOWN, else the dtor will point to no longer
97 * available memory if the extension has already been unloaded.
99 * @param f the factory to initialize; if NULL allocated on the heap
100 * @param fops the resource ops to assign to the factory
101 * @param data opaque user data; may be NULL
102 * @param dtor a destructor for the data; may be NULL
103 * @return \a f or an allocated resource factory
105 PHP_RAPHF_API php_resource_factory_t
*php_resource_factory_init(
106 php_resource_factory_t
*f
, php_resource_factory_ops_t
*fops
, void *data
,
107 void (*dtor
)(void *data
));
110 * Increase the refcount of the resource factory.
112 * @param rf the resource factory
113 * @return the new refcount
115 PHP_RAPHF_API
unsigned php_resource_factory_addref(php_resource_factory_t
*rf
);
118 * Destroy the resource factory.
120 * If the factory's refcount reaches 0, the \a dtor for \a data is called.
122 * @param f the resource factory
124 PHP_RAPHF_API
void php_resource_factory_dtor(php_resource_factory_t
*f
);
127 * Destroy and free the resource factory.
129 * Calls php_resource_factory_dtor() and frees \a f if the factory's refcount
132 * @param f the resource factory
134 PHP_RAPHF_API
void php_resource_factory_free(php_resource_factory_t
**f
);
137 * Construct a resource by the resource factory \a f
139 * @param f the resource factory
140 * @param init_arg for the resource constructor
141 * @return the new resource
143 PHP_RAPHF_API
void *php_resource_factory_handle_ctor(php_resource_factory_t
*f
,
147 * Create a copy of the resource \a handle
149 * @param f the resource factory
150 * @param handle the resource to copy
153 PHP_RAPHF_API
void *php_resource_factory_handle_copy(php_resource_factory_t
*f
,
157 * Destroy (and free) the resource
159 * @param f the resource factory
160 * @param handle the resource to destroy
162 PHP_RAPHF_API
void php_resource_factory_handle_dtor(php_resource_factory_t
*f
,
166 * Persistent handles storage
168 typedef struct php_persistent_handle_list
{
169 /** Storage of free resources */
171 /** Count of acquired resources */
173 } php_persistent_handle_list_t
;
176 * Definition of a persistent handle provider.
177 * Holds a resource factory an a persistent handle list.
179 typedef struct php_persistent_handle_provider
{
181 * The list of free handles.
182 * Hash of "ident" => array(handles) entries. Persistent handles are
183 * acquired out of this list.
185 php_persistent_handle_list_t list
;
188 * The resource factory.
189 * New handles are created by this factory.
191 php_resource_factory_t rf
;
192 } php_persistent_handle_provider_t
;
194 typedef struct php_persistent_handle_factory php_persistent_handle_factory_t
;
197 * Wakeup the persistent handle on re-acquisition.
199 typedef void (*php_persistent_handle_wakeup_t
)(
200 php_persistent_handle_factory_t
*f
, void **handle
);
202 * Retire the persistent handle on release.
204 typedef void (*php_persistent_handle_retire_t
)(
205 php_persistent_handle_factory_t
*f
, void **handle
);
208 * Definition of a persistent handle factory.
210 * php_persistent_handle_concede() will return a pointer to a
211 * php_persistent_handle_factory if a provider for the \a name has
212 * been registered with php_persistent_handle_provide().
214 struct php_persistent_handle_factory
{
215 /** The persistent handle provider */
216 php_persistent_handle_provider_t
*provider
;
217 /** The persistent handle wakeup routine; may be NULL */
218 php_persistent_handle_wakeup_t wakeup
;
219 /** The persistent handle retire routine; may be NULL */
220 php_persistent_handle_retire_t retire
;
222 /** The ident for which this factory manages resources */
225 /** Whether it has to be free'd on php_persistent_handle_abandon() */
226 unsigned free_on_abandon
:1;
230 * Register a persistent handle provider in MINIT.
232 * Registers a factory provider for \a name_str with \a fops resource factory
233 * ops. Call this in your MINIT.
235 * A php_resource_factory will be created with \a fops, \a data and \a dtor
236 * and will be stored together with a php_persistent_handle_list in the global
239 * A php_persistent_handle_factory can then be retrieved by
240 * php_persistent_handle_concede() at runtime.
242 * @param name the provider name, e.g. "http\Client\Curl"
243 * @param fops the resource factory ops
244 * @param data opaque user data
245 * @param dtor \a data destructor
246 * @return SUCCESS/FAILURE
248 PHP_RAPHF_API ZEND_RESULT_CODE
php_persistent_handle_provide(
249 zend_string
*name
, php_resource_factory_ops_t
*fops
,
250 void *data
, void (*dtor
)(void *));
253 * Retrieve a persistent handle factory at runtime.
255 * If a persistent handle provider has been registered for \a name, a new
256 * php_persistent_handle_factory creating resources in the \a ident
257 * namespace will be constructed.
259 * The wakeup routine \a wakeup and the retire routine \a retire will be
260 * assigned to the new php_persistent_handle_factory.
262 * @param a pointer to a factory; allocated on the heap if NULL
263 * @param name the provider name, e.g. "http\Client\Curl"
264 * @param ident the subsidiary namespace, e.g. "php.net:80"
265 * @param wakeup any persistent handle wakeup routine
266 * @param retire any persistent handle retire routine
267 * @return \a a or an allocated persistent handle factory
269 PHP_RAPHF_API php_persistent_handle_factory_t
*php_persistent_handle_concede(
270 php_persistent_handle_factory_t
*a
,
271 zend_string
*name
, zend_string
*ident
,
272 php_persistent_handle_wakeup_t wakeup
,
273 php_persistent_handle_retire_t retire
);
276 * Abandon the persistent handle factory.
278 * Destroy a php_persistent_handle_factory created by
279 * php_persistent_handle_concede(). If the memory for the factory was allocated,
280 * it will automatically be free'd.
282 * @param a the persistent handle factory to destroy
284 PHP_RAPHF_API
void php_persistent_handle_abandon(
285 php_persistent_handle_factory_t
*a
);
288 * Acquire a persistent handle.
290 * That is, either re-use a resource from the free list or create a new handle.
292 * If a handle is acquired from the free list, the
293 * php_persistent_handle_factory::wakeup callback will be executed for that
296 * @param a the persistent handle factory
297 * @param init_arg the \a init_arg for php_resource_factory_handle_ctor()
298 * @return the acquired resource
300 PHP_RAPHF_API
void *php_persistent_handle_acquire(
301 php_persistent_handle_factory_t
*a
, void *init_arg
);
304 * Release a persistent handle.
306 * That is, either put it back into the free list for later re-use or clean it
307 * up with php_resource_factory_handle_dtor().
309 * If a handle is put back into the free list, the
310 * php_persistent_handle_factory::retire callback will be executed for that
313 * @param a the persistent handle factory
314 * @param handle the handle to release
316 PHP_RAPHF_API
void php_persistent_handle_release(
317 php_persistent_handle_factory_t
*a
, void *handle
);
320 * Copy a persistent handle.
322 * Let the underlying resource factory copy the \a handle.
324 * @param a the persistent handle factory
325 * @param handle the resource to accrete
327 PHP_RAPHF_API
void *php_persistent_handle_accrete(
328 php_persistent_handle_factory_t
*a
, void *handle
);
331 * Retrieve persistent handle resource factory ops.
333 * These ops can be used to mask a persistent handle factory as
334 * resource factory itself, so you can transparently use the
335 * resource factory API, both for persistent and non-persistent
339 * ~~~~~~~~~~~~~~~{.c}
340 * php_resource_factory_t *create_my_rf(zend_string *persistent_id)
342 * php_resource_factory_t *rf;
344 * if (persistent_id) {
345 * php_persistent_handle_factory_t *pf;
346 * php_resource_factory_ops_t *ops;
347 * zend_string *ns = zend_string_init("my", 2, 1);
349 * ops = php_persistent_handle_get_resource_factory_ops();
350 * pf = php_persistent_handle_concede(NULL, ns, persistent_id, NULL, NULL);
351 * rf = php_persistent_handle_resource_factory_init(NULL, pf);
352 * zend_string_release(ns);
354 * rf = php_resource_factory_init(NULL, &myops, NULL, NULL);
360 PHP_RAPHF_API php_resource_factory_ops_t
*
361 php_persistent_handle_get_resource_factory_ops(void);
364 * Create a resource factory for persistent handles.
366 * This will create a resource factory with persistent handle ops, which wraps
367 * the provided reource factory \a pf.
369 * @param a the persistent handle resource factory to initialize
370 * @param pf the resource factory to wrap
372 PHP_RAPHF_API php_resource_factory_t
*
373 php_persistent_handle_resource_factory_init(php_resource_factory_t
*a
,
374 php_persistent_handle_factory_t
*pf
);
377 * Check whether a resource factory is a persistent handle resource factory.
379 * @param a the resource factory to check
381 PHP_RAPHF_API zend_bool
php_resource_factory_is_persistent(
382 php_resource_factory_t
*a
);
385 * Clean persistent handles up.
387 * Destroy persistent handles of provider \a name and in subsidiary
388 * namespace \a ident.
390 * If \a name is NULL, all persistent handles of all providers with a
391 * matching \a ident will be cleaned up.
393 * If \a identr is NULL all persistent handles of the provider will be
396 * Ergo, if both, \a name and \a ident are NULL, then all
397 * persistent handles will be cleaned up.
399 * You must call this in MSHUTDOWN, if your resource factory ops hold a
400 * registered php_resource_factory::dtor, else the dtor will point to
401 * memory not any more available if the extension has already been unloaded.
403 * @param name the provider name; may be NULL
404 * @param ident the subsidiary namespace name; may be NULL
406 PHP_RAPHF_API
void php_persistent_handle_cleanup(zend_string
*name
,
410 * Retrieve statistics about the current process/thread's persistent handles.
412 * @return a HashTable like:
424 PHP_RAPHF_API HashTable
*php_persistent_handle_statall(HashTable
*ht
);
426 #endif /* PHP_RAPHF_H */
434 * vim600: noet sw=4 ts=4 fdm=marker
435 * vim<600: noet sw=4 ts=4