Ресурсы
| ||||||||||||||||||||||||||||||||||||||
|
ZEND_API int zend_register_list_destructors_ex(rsrc_dtor_func_t ld, rsrc_dtor_func_t pld, char *type_name, int module_number); |
Есть две разновидности обработчиков уничтожения ресурса, которые вы можете передавать этой функции: обработчик нормальных ресурсов и обработчик постоянных ресурсов. Постоянные ресурсы используются, например, для соединений с базами данных (БД). При регистрации ресурса обязан иметься один из этих обработчиков. Для другого обработчика просто передайте NULL.
zend_register_list_destructors_ex() принимает следующие параметры: return-значение это уникальный целочисленный ID (идентификатор) вашего типа ресурса. Обработчик уничтожения ресурса (нормального или постоянного) имеет следующий прототип:
Передаваемый rsrc это указатель но следующую структуру: Член void *ptr это фактический указатель на ваш ресурс. Теперь мы знаем, как начать: мы определяем наш собственный ресурс,
который хотим зарегистрировать в Zend. Это простая структура с двумя
целочисленными членами: Наш обработчик уничтожения ресурса будет, вероятно, выглядеть так: Примечание: важно подчеркнуть: Если ваш ресурс это более сложная структура, которая к тому
же содержит указатели на память, выделенную в процессе работы, вы должны освободить их перед освобождением самого ресурса! Теперь, когда мы определили что такое наш ресурс и обработчик уничтожения ресурса, создать глобальную переменную с расширение, содержащую ID ресурса, чтобы можно
было получить к нему доступ из любой функции определить имя ресурса написать обработчик уничтожения ресурса и, наконец, зарегистрировать обработчик Для регистрации нового ресурса вы можете использовать либо функцию zend_register_resource(),
либо макрос ZEND_REGISTER_RESOURE(), определённые в zend_list.h. хотя аргументы для них обоих соответствуют
1:1, лучше всегда использовать макросы для обеспечения совместимости в будущем:
ld Вызов обработчика уничтожения нормального ресурса
pld Вызов обработчика уничтожения постоянного ресурса
type_name Строка, специфицирующая имя вашего ресурса. Хорошо бы всегда специфицировать
уникальное имя типа ресурса РНР, чтобы, если пользователь, например, вызовет var_dump($resource);,
он получил также имя ресурса. module_number
module_number является доступным автоматически в вашей функции
PHP_MINIT_FUNCTION, и, следовательно, вы просто передаёте его.
void resource_destruction_handler(zend_rsrc_list_entry *rsrc TSRMLS_DC);
typedef struct _zend_rsrc_list_entry {
void *ptr;
int type;
int refcount;
} zend_rsrc_list_entry;
typedef struct {
int resource_link;
int resource_type;
} my_resource;
void my_destruction_handler(zend_rsrc_list_entry *rsrc TSRMLS_DC) {
// Скорее всего вам придётся привести/cast void-указатель к типу вашей структуры
my_resource *my_rsrc = (my_resource *) rsrc->ptr;
// Теперь делайте с вашим ресурсом всё необходимое. Закрывайте
// Файлы, Сокеты, освобождайте память etc.
// Также не забудьте реально освободить память вашего ресурса!
do_whatever_needs_to_be_done_with_the_resource(my_rsrc);
}
мы можем выполнить остальные шаги:
//Где-либо в вашем расширении определите переменную для ваших зарегистрированных ресурсов.
// Как вам нравится ’le’: это просто означает ’list entry/вхождение в списке’.
static int le_myresource;
// Определите имя вашего ресурса
#define le_myresource_name "My type of resource"
[...]
// Теперь определите обработчик уничтожения вашего ресурса
void my_destruction_handler(zend_rsrc_list_entry *rsrc TSRMLS_DC) {
my_resource *my_rsrc = (my_resource *) rsrc->ptr;
do_whatever_needs_to_be_done_with_the_resource(my_rsrc);
}
[...]
PHP_MINIT_FUNCTION(my_extension) {
// Заметьте, что ’module_number’ уже предоставлен посредством
// определения функции PHP_MINIT_FUNCTION().
le_myresource = zend_register_resource_destructors_ex(my_destruction_handler, NULL, le_myresource_name, module_number);
// Вы можете регистрировать дополнительные ресурсы, инициализировать ваши
// глобальные переменные, константы ...
}
int ZEND_REGISTER_RESOURCE(zval *rsrc_result, void *rsrc_pointer, int rsrc_type);
rsrc_result | Это уже инициализированный zval * -контейнер. |
rsrc_pointer | Указатель на ваш ресурс. |
rsrc_type | Тип, который вы получили, когда регистрировали обработчик уничтожения ресурса. Если вы следуете схеме именования, это может быть le_myresource. |
return-значение это уникальный целочисленный идентификатор данного ресурса.
Когда вы регистрируете новый ресурс, он вставляется во внутренний список Zend, а результат просто хранится в данном zval * -контейнере:
rsrc_id = zend_list_insert(rsrc_pointer, rsrc_type); if (rsrc_result) { rsrc_result->value.lval = rsrc_id; rsrc_result->type = IS_RESOURCE; } return rsrc_id; |
Возвращаемый rsrc_id уникально идентифицирует вновь зарегистрированный ресурс. Вы можете использовать макрос RETURN_RESOURE для возвращения его пользователю:
RETURN_RESOURCE(rsrc_id) |
Примечание: обычно, если вы хотите немедленно возвратить ресурс пользователю, вы специфицируете return_value как zval * -контейнер.
Теперь Zend отслеживает все обращения к данному ресурсу. Как только
все ссылки на данный ресурс будут утеряны, вызывается обработчик уничтожения
ресурса, зарегистрированный ранее для данного ресурса.
Удобно здесь то, что вам не нужно заботиться об утечках памяти, появляющихся
при выделении памяти в вашем модуле - просто зарегистрируйте все выделения
памяти для вашего вызывающего скрипта как ресурсы. Если скрипт определяет,
что эти участки памяти - ресурсы больше ему не нужны, Zend выявит это и сообщит вам.
Получив тот ресурс в некоторой точке, пользователь передаёт его обратно в одну из ваших функций. Контейнер value.lval внутри контейнера zval * содержит ключ/key к вашему ресурсу и, таким образом, может быть использован для получения этого ресурса с помощью макроса ZEND_FETCH_RESOURCE:
ZEND_FETCH_RESOURCE(rsrc, rsrc_type, rsrc_id, default_rsrc_id, resource_type_name, resource_type) |
rsrc | Это ваш указатель, указывающий на ваш ранее зарегистрированный ресурс. |
rsrc_type | Это аргумент приведения типа/typecast для вашего указателя, например, myresource *. |
rsrc_id | Это адрес zval * -контейнера, переданный пользователем в вашу функцию, например, g. &z_resource, если дан zval *z_resource. |
default_rsrc_id | Это целое число специфицирует ID ресурса по умолчанию, если ресурс не может быть получен, или -1. |
resource_type_name | Это имя запрошенного ресурса. Это строка, которая используется, когда ресурс не может быть найден или неверен, для создания сообщения об ошибке. |
resource_type | resource_type, который вы получили, когда регистрировали обработчик уничтожения ресурса. В нашем примере это был le_myresource. |
Этот макрос не имеет return-значения. Это сделано для удобства разработчиков. Он заботится о передаче TSRMLS-аргументов, а также проверяет, может ли ресурс быть получен. Он вызывает появление сообщения-предупреждения и возвращает текущую PHP-функцию с NULL, если была проблема с получением ресурса.
Чтобы форсировать удаление ресурса из списка, используйте функцию zend_list_delete().
Вы можете также форсировать увеличение счётчика ссылок, если знаете, что
создаёте другую ссылку на ранее размещённое значение (например, если вы
автоматически повторно используете ссылку БД). В этом случае используйте
функцию zend_list_addref().
Для поиска ранее выделенных вхождений ресурсов используйте
zend_list_find(). Полный API можно найти в zend_list.h.
| ||||||
|
Нет комментариев. Ваш будет первым!