From c7de5d15b73573d35599078a48f9a078f4c51d40 Mon Sep 17 00:00:00 2001 From: Harald Radi Date: Tue, 11 Feb 2003 00:55:27 +0000 Subject: [PATCH] clean up source and improve hashing for implicitly created objects (aka return values) --- ext/rpc/handler.h | 1 + ext/rpc/rpc.c | 93 +++++++++++++++++++++-------------------------- ext/rpc/rpc.h | 36 ++++++++++++++++++ 3 files changed, 79 insertions(+), 51 deletions(-) diff --git a/ext/rpc/handler.h b/ext/rpc/handler.h index a01598113b..cbb868265c 100644 --- a/ext/rpc/handler.h +++ b/ext/rpc/handler.h @@ -116,6 +116,7 @@ typedef struct _rpc_class_hash { typedef struct _rpc_internal { MUTEX_T mx_handler; TsHashTable function_table; + zend_bool free_function_table; rpc_object_handlers **handlers; rpc_class_hash *hash; zend_class_entry *ce; diff --git a/ext/rpc/rpc.c b/ext/rpc/rpc.c index 1eae43234e..6955d8b545 100644 --- a/ext/rpc/rpc.c +++ b/ext/rpc/rpc.c @@ -229,6 +229,11 @@ static void rpc_instance_dtor(void *pDest) RPC_HT(*intern)->rpc_dtor((*intern)->data); + tsrm_mutex_free((*intern)->mx_handler); + if ((*intern)->free_function_table) { + zend_ts_hash_destroy(&((*intern)->function_table)); + } + pefree(*intern, TRUE); } @@ -439,7 +444,6 @@ ZEND_API ZEND_FUNCTION(rpc_load) zval *object = getThis(); zval ***args, ***args_free; zend_uint num_args = ZEND_NUM_ARGS(); - zend_class_entry overloaded_class_entry; rpc_class_hash *class_hash; rpc_internal *intern; rpc_string hash_val, class_val; @@ -474,7 +478,7 @@ ZEND_API ZEND_FUNCTION(rpc_load) GET_ARGS_EX(num_args, args, args_free, 1); /* if classname != integer */ - if ((zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, 1 TSRMLS_CC, "l", &class_val.str) != SUCCESS) || + if ((zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, 1 TSRMLS_CC, "l", &class_val.len) != SUCCESS) || /* or we have no hash function */ !(RPC_HT(intern)->rpc_hash) || /* or integer hashing is not allowed */ @@ -495,12 +499,10 @@ ZEND_API ZEND_FUNCTION(rpc_load) /* check if already hashed */ if ((class_hash = rpc_class_hash_find(&hash_val)) == NULL) { - rpc_class_hash **class_hash_find; - ALLOC_CLASS_HASH(class_hash, intern->handlers); /* do hashing */ - if (RPC_HT(intern)->rpc_hash(class_val, (rpc_string *)(class_hash), NULL, num_args, arg_types, CLASS) != SUCCESS) { + if (RPC_HT(intern)->rpc_hash(class_val, (rpc_string *) class_hash, NULL, num_args, arg_types, CLASS) != SUCCESS) { /* TODO: exception */ ZVAL_NULL(object); return; @@ -508,39 +510,22 @@ ZEND_API ZEND_FUNCTION(rpc_load) /* overload class entry */ RPC_HT(intern)->rpc_name(class_val, &class_val, NULL, CLASS); - INIT_CLASS_ENTRY(overloaded_class_entry, NULL, NULL); - overloaded_class_entry.name = class_val.str; - overloaded_class_entry.name_length = class_val.len; - class_hash->ce = zend_register_internal_class_ex(&overloaded_class_entry, intern->ce, NULL TSRMLS_CC); - intern->ce = class_hash->ce; - intern->function_table.hash = intern->ce->function_table; + OVERLOAD_RPC_CLASS(class_val, intern, class_hash); /* register with non-hashed key * also track all instaces in a llist for destruction later on, because there might be duplicate entries in * the hashtable and we can't determine if a pointer references to an already freed element */ - tsrm_mutex_lock(classes.mx_writer); - zend_ts_hash_add(&classes, hash_val.str, hash_val.len + 1, &class_hash, sizeof(rpc_class_hash *), (void **) &class_hash_find); - zend_llist_add_element(&classes_list, class_hash_find); - tsrm_mutex_unlock(classes.mx_writer); - - if (class_hash->name.str) { - /* register string hashcode */ - zend_ts_hash_add(&classes, class_hash->name.str, class_hash->name.len + 1, &class_hash, sizeof(rpc_class_hash *), NULL); - } else if (!class_hash->name.str && (RPC_HT(intern)->hash_type & HASH_AS_INT)) { - /* register int hashcode */ - zend_ts_hash_index_update(&classes, class_hash->name.len, &class_hash, sizeof(rpc_class_hash *), NULL); - } + REGISTER_RPC_CLASS(class_val, class_hash); } else { - intern->ce = class_hash->ce; + INIT_RPC_OBJECT(intern, class_hash); } FREE_SIGNATURE(hash_val, arg_types); } else { - /* overload class entry */ - INIT_CLASS_ENTRY(overloaded_class_entry, class_val.str, NULL); - intern->ce = zend_register_internal_class_ex(&overloaded_class_entry, intern->ce, NULL TSRMLS_CC); - intern->function_table.hash = intern->ce->function_table; + /* Copy the function table hash for this object, so that it is separated + * from the "global" table */ + SEPARATE_RPC_CLASS(intern); } } } else { @@ -548,20 +533,18 @@ ZEND_API ZEND_FUNCTION(rpc_load) if ((class_hash = rpc_class_hash_find(&hash_val)) == NULL) { ALLOC_CLASS_HASH(class_hash, intern->handlers); + class_val.str = NULL; class_hash->name.str = NULL; class_hash->name.len = class_val.len; /* overload class entry */ RPC_HT(intern)->rpc_name(class_val, &class_val, NULL, CLASS); - INIT_CLASS_ENTRY(overloaded_class_entry, class_val.str, NULL); - class_hash->ce = zend_register_internal_class_ex(&overloaded_class_entry, intern->ce, NULL TSRMLS_CC); - intern->ce = class_hash->ce; - intern->function_table.hash = intern->ce->function_table; + OVERLOAD_RPC_CLASS(class_val, intern, class_hash); /* register int hashcode, we don't know more */ - zend_ts_hash_index_update(&classes, class_hash->name.len, &class_hash, sizeof(rpc_class_hash *), NULL); + REGISTER_RPC_CLASS(class_val, class_hash); } else { - intern->ce = class_hash->ce; + INIT_RPC_OBJECT(intern, class_hash); } } @@ -795,6 +778,7 @@ ZEND_API zend_object_value rpc_objects_new(zend_class_entry *class_type TSRMLS_D intern->ce = class_type; intern->data = NULL; + intern->free_function_table = 0; intern->function_table.reader = 0; intern->function_table.mx_reader = tsrm_mutex_alloc(); intern->function_table.mx_writer = tsrm_mutex_alloc(); @@ -893,7 +877,7 @@ static rpc_class_hash *rpc_class_hash_find(rpc_string *name) ZEND_API zval* _rpc_object_from_data(zval *z, rpc_handler_entry *handler, void *data, rpc_class_hash *class_hash) { rpc_internal *intern; - rpc_string name = {NULL, 0}; + rpc_string hash, name = {NULL, 0}; TSRMLS_FETCH(); if (z == NULL) { @@ -908,27 +892,34 @@ ZEND_API zval* _rpc_object_from_data(zval *z, rpc_handler_entry *handler, void * return NULL; } + intern->ce = *(handler->ce); intern->data = data; - if (class_hash == NULL) { - if (handler->handlers->rpc_name(name, &name, data, CLASS) == SUCCESS) { - class_hash = rpc_class_hash_find(&name); - } else { - ALLOC_CLASS_HASH(class_hash, intern->handlers); + if ((handler->handlers->rpc_hash) && + (handler->handlers->rpc_hash(name, &hash, data, 0, "", CLASS) == SUCCESS)) { + /* We are hashing, try to find an appropriate hash or create a new one */ + if ((class_hash == NULL) && + ((class_hash = rpc_class_hash_find(&hash)) == NULL)) { + ALLOC_CLASS_HASH(class_hash, intern->handlers); - if (class_hash == NULL) { - /* TODO: exception */ - return NULL; + class_hash->name = hash; + + if (handler->handlers->rpc_name(hash, &name, data, CLASS) != SUCCESS) { + /* TODO exception */ + } + + OVERLOAD_RPC_CLASS(name, intern, class_hash); + REGISTER_RPC_CLASS(name, class_hash); + } else { + INIT_RPC_OBJECT(intern, class_hash); } - - /* Copy the function table hash for this object, so that it is separated - * from the "global" table */ - zend_ts_hash_init(&(intern->function_table), 0, NULL, NULL, TRUE); - zend_hash_copy(&intern->function_table.hash, &((*(handler->ce))->function_table), NULL, NULL, 0); - } - } - RPC_CLASS(intern) = class_hash; + RPC_CLASS(intern) = class_hash; + } else { + /* Copy the function table hash for this object, so that it is separated + * from the "global" table */ + SEPARATE_RPC_CLASS(intern); + } return z; } diff --git a/ext/rpc/rpc.h b/ext/rpc/rpc.h index 7a90290a16..07c760c36c 100644 --- a/ext/rpc/rpc.h +++ b/ext/rpc/rpc.h @@ -134,4 +134,40 @@ _class_hash->handlers = _handlers; \ } +#define INIT_RPC_OBJECT(__intern, __clh) \ + (__intern)->ce = (__clh)->ce; \ + (__intern)->function_table.hash = (__intern)->ce->function_table; + +#define OVERLOAD_RPC_CLASS(__name, __intern, __clh) { \ + zend_class_entry overloaded_class_entry; \ + INIT_CLASS_ENTRY(overloaded_class_entry, NULL, NULL); \ + overloaded_class_entry.name = __name.str; \ + overloaded_class_entry.name_length = (__name.str != NULL) ? __name.len : 0; \ + (__clh)->ce = zend_register_internal_class_ex(&overloaded_class_entry, (__intern)->ce, NULL TSRMLS_CC); \ + INIT_RPC_OBJECT(__intern, __clh); \ + } + +#define SEPARATE_RPC_CLASS(__intern) \ + (__intern)->free_function_table = 1; \ + zend_ts_hash_init(&((__intern)->function_table), 0, NULL, NULL, TRUE); \ + zend_hash_copy(&((__intern)->function_table.hash), &((__intern)->ce->function_table), NULL, NULL, 0); + +#define REGISTER_RPC_CLASS(__name, __class_hash) { \ + rpc_class_hash **_tmp; \ + if ((__name).str != NULL) { \ + zend_ts_hash_add(&classes, (__name).str, (__name).len + 1, &(__class_hash), sizeof(rpc_class_hash *), (void **) &_tmp); \ + } \ + \ + tsrm_mutex_lock(classes.mx_writer); \ + zend_llist_add_element(&classes_list, _tmp); \ + tsrm_mutex_unlock(classes.mx_writer); \ + \ + if ((__class_hash)->name.str) { \ + zend_ts_hash_add(&classes, (__class_hash)->name.str, (__class_hash)->name.len + 1, &(__class_hash), sizeof(rpc_class_hash *), NULL); \ + } else { \ + zend_ts_hash_index_update(&classes, class_hash->name.len, &class_hash, sizeof(rpc_class_hash *), NULL); \ + } \ + } + + #endif \ No newline at end of file -- 2.40.0