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);
}
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;
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 */
/* 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;
/* 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 {
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);
}
}
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();
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) {
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;
}
_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