pooling and singleton finally work

This commit is contained in:
Harald Radi 2002-06-10 21:16:25 +00:00
parent f1f6818c20
commit fd8082ef67
4 changed files with 160 additions and 51 deletions

View file

@ -91,22 +91,24 @@ typedef struct _rpc_handler_entry {
/* class/method/function hash */ /* class/method/function hash */
typedef struct _rpc_class_hash { typedef struct _rpc_class_hash {
rpc_string name; /* must be first entry */ rpc_string name; /* must be first entry */
TsHashTable methods; zend_bool poolable;
TsHashTable properties; zend_bool singleton;
zend_class_entry *ce; TsHashTable methods;
TsHashTable properties;
rpc_object_handlers **handlers;
zend_class_entry *ce;
void *data;
} rpc_class_hash; } rpc_class_hash;
/* internal data */ /* internal data */
typedef struct _rpc_internal { typedef struct _rpc_internal {
zend_bool poolable;
zend_bool singleton;
zend_class_entry *ce;
rpc_object_handlers **handlers;
void *data;
rpc_class_hash *hash;
TsHashTable function_table;
MUTEX_T mx_handler; MUTEX_T mx_handler;
TsHashTable function_table;
rpc_object_handlers **handlers;
rpc_class_hash *hash;
zend_class_entry *ce;
void *data;
} rpc_internal; } rpc_internal;
/* proxy data */ /* proxy data */

View file

@ -29,16 +29,6 @@ ZEND_FUNCTION(rpc_get);
ZEND_FUNCTION(rpc_singleton); ZEND_FUNCTION(rpc_singleton);
ZEND_FUNCTION(rpc_poolable); ZEND_FUNCTION(rpc_poolable);
ZEND_BEGIN_MODULE_GLOBALS(rpc)
TsHashTable *proxy;
ZEND_END_MODULE_GLOBALS(rpc)
#ifdef ZTS
#define RPC_G(v) TSRMG(rpc_globals_id, zend_rpc_globals *, v)
#else
#define RPC_G(v) (rpc_globals.v)
#endif
#define phpext_rpc_ptr &rpc_module_entry #define phpext_rpc_ptr &rpc_module_entry
#endif /* PHP_RPC_H */ #endif /* PHP_RPC_H */

View file

@ -10,16 +10,15 @@
#include "rpc.h" #include "rpc.h"
#include "layer.h" #include "layer.h"
ZEND_DECLARE_MODULE_GLOBALS(rpc) static void rpc_instance_dtor(void *);
static void rpc_globals_ctor(zend_rpc_globals * TSRMLS_DC);
static void rpc_class_dtor(void *); static void rpc_class_dtor(void *);
static void rpc_string_dtor(void *); static void rpc_string_dtor(void *);
static void rpc_export_functions(char *, zend_class_entry *, function_entry[] TSRMLS_DC);
static zend_object_value rpc_objects_new(zend_class_entry * TSRMLS_DC); static zend_object_value rpc_objects_new(zend_class_entry * TSRMLS_DC);
static void rpc_objects_delete(void *object, zend_object_handle handle TSRMLS_DC); static void rpc_objects_delete(void *object, zend_object_handle handle TSRMLS_DC);
static int zend_ts_hash_remove_key_or_index(TsHashTable *ht, char *arKey, uint nKeyLength, void **pData);
/* object handler */ /* object handler */
static zval* rpc_read(zval *, zval *, int TSRMLS_DC); static zval* rpc_read(zval *, zval *, int TSRMLS_DC);
static void rpc_write(zval *, zval *, zval * TSRMLS_DC); static void rpc_write(zval *, zval *, zval * TSRMLS_DC);
@ -90,6 +89,7 @@ zend_module_entry rpc_module_entry = {
zend_class_entry rpc_class_entry; zend_class_entry rpc_class_entry;
static HashTable *handlers; static HashTable *handlers;
static TsHashTable *pool;
static TsHashTable *classes; static TsHashTable *classes;
static zend_llist *classes_list; static zend_llist *classes_list;
@ -100,10 +100,6 @@ ZEND_GET_MODULE(rpc);
ZEND_INI_BEGIN() ZEND_INI_BEGIN()
ZEND_INI_END() ZEND_INI_END()
static void rpc_globals_ctor(zend_rpc_globals *rpc_globals TSRMLS_DC)
{
}
/* {{{ ZEND_MINIT_FUNCTION /* {{{ ZEND_MINIT_FUNCTION
*/ */
ZEND_MINIT_FUNCTION(rpc) ZEND_MINIT_FUNCTION(rpc)
@ -115,10 +111,12 @@ ZEND_MINIT_FUNCTION(rpc)
rpc_entry = zend_register_internal_class(&rpc_class_entry TSRMLS_CC); rpc_entry = zend_register_internal_class(&rpc_class_entry TSRMLS_CC);
handlers = (HashTable *) pemalloc(sizeof(HashTable), TRUE); handlers = (HashTable *) pemalloc(sizeof(HashTable), TRUE);
pool = (TsHashTable *) pemalloc(sizeof(TsHashTable), TRUE);
classes = (TsHashTable *) pemalloc(sizeof(TsHashTable), TRUE); classes = (TsHashTable *) pemalloc(sizeof(TsHashTable), TRUE);
classes_list = (zend_llist *) pemalloc(sizeof(zend_llist), TRUE); classes_list = (zend_llist *) pemalloc(sizeof(zend_llist), TRUE);
zend_hash_init(handlers, 0, NULL, NULL, TRUE); zend_hash_init(handlers, 0, NULL, NULL, TRUE);
zend_ts_hash_init(pool, sizeof(rpc_internal **), NULL, rpc_instance_dtor, TRUE);
zend_ts_hash_init(classes, 0, NULL, NULL, TRUE); zend_ts_hash_init(classes, 0, NULL, NULL, TRUE);
zend_llist_init(classes_list, sizeof(rpc_class_hash **), rpc_class_dtor, TRUE); zend_llist_init(classes_list, sizeof(rpc_class_hash **), rpc_class_dtor, TRUE);
@ -141,7 +139,6 @@ ZEND_MINIT_FUNCTION(rpc)
zend_register_ini_entries(HANDLER.ini, module_number TSRMLS_CC); zend_register_ini_entries(HANDLER.ini, module_number TSRMLS_CC);
} }
ZEND_INIT_MODULE_GLOBALS(rpc, rpc_globals_ctor, NULL);
REGISTER_INI_ENTRIES(); REGISTER_INI_ENTRIES();
return SUCCESS; return SUCCESS;
@ -153,8 +150,9 @@ ZEND_MINIT_FUNCTION(rpc)
ZEND_MSHUTDOWN_FUNCTION(rpc) ZEND_MSHUTDOWN_FUNCTION(rpc)
{ {
/* destroy instances first */ /* destroy instances first */
zend_ts_hash_destroy(classes); zend_ts_hash_destroy(pool);
zend_ts_hash_destroy(classes);
zend_llist_destroy(classes_list); zend_llist_destroy(classes_list);
zend_hash_destroy(handlers); zend_hash_destroy(handlers);
@ -184,6 +182,10 @@ static void rpc_class_dtor(void *pDest)
hash = (rpc_class_hash **) pDest; hash = (rpc_class_hash **) pDest;
if ((*hash)->singleton) {
RPC_HT(*hash)->rpc_dtor((*hash)->data);
}
zend_ts_hash_destroy(&((*hash)->methods)); zend_ts_hash_destroy(&((*hash)->methods));
zend_ts_hash_destroy(&((*hash)->properties)); zend_ts_hash_destroy(&((*hash)->properties));
@ -201,6 +203,17 @@ static void rpc_string_dtor(void *pDest)
pefree(*string, TRUE); pefree(*string, TRUE);
} }
static void rpc_instance_dtor(void *pDest)
{
rpc_internal **intern;
intern = (rpc_internal **) pDest;
RPC_HT(*intern)->rpc_dtor((*intern)->data);
pefree(*intern, TRUE);
}
static zend_object_value rpc_objects_new(zend_class_entry *class_type TSRMLS_DC) static zend_object_value rpc_objects_new(zend_class_entry *class_type TSRMLS_DC)
{ {
zend_object_value *zov; zend_object_value *zov;
@ -215,8 +228,6 @@ static zend_object_value rpc_objects_new(zend_class_entry *class_type TSRMLS_DC)
intern->ce = class_type; intern->ce = class_type;
intern->data = NULL; intern->data = NULL;
intern->singleton = FALSE;
intern->poolable = FALSE;
intern->function_table.hash = intern->ce->function_table; intern->function_table.hash = intern->ce->function_table;
intern->function_table.reader = 0; intern->function_table.reader = 0;
intern->function_table.mx_reader = tsrm_mutex_alloc(); intern->function_table.mx_reader = tsrm_mutex_alloc();
@ -249,7 +260,7 @@ static zend_object_value rpc_create_proxy(TSRMLS_D)
*/ */
/* tsrm_mutex_lock(proxy->mx_writer); /* tsrm_mutex_lock(proxy->mx_writer);
{ {
zov->handle = zend_hash_next_free_element(&(proxy->hash)); zov->handle = zend_hash_next_free_element(TS_HASH(proxy));
zend_ts_hash_next_index_insert(proxy, &proxy_intern, sizeof(rpc_proxy *), NULL); zend_ts_hash_next_index_insert(proxy, &proxy_intern, sizeof(rpc_proxy *), NULL);
} }
tsrm_mutex_unlock(proxy->mx_writer); tsrm_mutex_unlock(proxy->mx_writer);
@ -262,11 +273,19 @@ static zend_object_value rpc_create_proxy(TSRMLS_D)
static void rpc_objects_delete(void *object, zend_object_handle handle TSRMLS_DC) static void rpc_objects_delete(void *object, zend_object_handle handle TSRMLS_DC)
{ {
rpc_internal *intern = (rpc_internal *) object; rpc_internal *intern = (rpc_internal *) object;
if (intern->poolable) { if (RPC_CLASS(intern) && RPC_CLASS(intern)->singleton) {
pefree(intern, TRUE);
} else if (RPC_CLASS(intern) && RPC_CLASS(intern)->poolable) {
if (RPC_CLASS(intern)->name.str) {
zend_ts_hash_add(pool, RPC_CLASS(intern)->name.str, RPC_CLASS(intern)->name.len + 1, &intern, sizeof(rpc_internal *), NULL);
} else {
zend_ts_hash_index_update(pool, RPC_CLASS(intern)->name.len + 1, &intern, sizeof(rpc_internal *), NULL);
} }
/* TODO: pool */ } else {
pefree(intern, TRUE); RPC_HT(intern)->rpc_dtor(intern->data);
pefree(intern, TRUE);
}
} }
static zval* rpc_read(zval *object, zval *member, int type TSRMLS_DC) static zval* rpc_read(zval *object, zval *member, int type TSRMLS_DC)
@ -479,6 +498,10 @@ ZEND_FUNCTION(rpc_load)
/* set up the cache */ /* set up the cache */
zend_ts_hash_init(&(class_hash->methods), 0, NULL, rpc_string_dtor, TRUE); zend_ts_hash_init(&(class_hash->methods), 0, NULL, rpc_string_dtor, TRUE);
zend_ts_hash_init(&(class_hash->properties), 0, NULL, rpc_string_dtor, TRUE); zend_ts_hash_init(&(class_hash->properties), 0, NULL, rpc_string_dtor, TRUE);
class_hash->handlers = intern->handlers;
class_hash->singleton = FALSE;
class_hash->poolable = FALSE;
class_hash->data = NULL;
/* do hashing */ /* do hashing */
if (RPC_HT(intern)->rpc_hash(class_val, (rpc_string *)(class_hash), num_args, arg_types, CLASS) != SUCCESS) { if (RPC_HT(intern)->rpc_hash(class_val, (rpc_string *)(class_hash), num_args, arg_types, CLASS) != SUCCESS) {
@ -516,9 +539,9 @@ ZEND_FUNCTION(rpc_load)
FREE_SIGNATURE(hash_val, arg_types); FREE_SIGNATURE(hash_val, arg_types);
} else { } else {
/* overload class entry */ /* overload class entry */
INIT_CLASS_ENTRY(overloaded_class_entry, class_val.str, NULL); 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->ce = zend_register_internal_class_ex(&overloaded_class_entry, intern->ce, NULL TSRMLS_CC);
} }
} }
} else { } else {
@ -529,6 +552,10 @@ ZEND_FUNCTION(rpc_load)
/* set up the cache */ /* set up the cache */
class_hash->name.str = NULL; class_hash->name.str = NULL;
class_hash->name.len = class_val.len; class_hash->name.len = class_val.len;
class_hash->handlers = intern->handlers;
class_hash->singleton = FALSE;
class_hash->poolable = FALSE;
class_hash->data = NULL;
zend_ts_hash_init(&(class_hash->methods), 0, NULL, rpc_string_dtor, TRUE); zend_ts_hash_init(&(class_hash->methods), 0, NULL, rpc_string_dtor, TRUE);
zend_ts_hash_init(&(class_hash->properties), 0, NULL, rpc_string_dtor, TRUE); zend_ts_hash_init(&(class_hash->properties), 0, NULL, rpc_string_dtor, TRUE);
@ -549,11 +576,24 @@ ZEND_FUNCTION(rpc_load)
/* if hash function available */ /* if hash function available */
if (RPC_HT(intern)->rpc_hash) { if (RPC_HT(intern)->rpc_hash) {
rpc_internal *pool_intern;
/* assign cache structure */ /* assign cache structure */
intern->hash = class_hash; RPC_CLASS(intern) = class_hash;
/* call the rpc ctor */ if (zend_ts_hash_remove_key_or_index(pool, RPC_CLASS(intern)->name.str, RPC_CLASS(intern)->name.len + 1, (void **) &pool_intern) == SUCCESS) {
retval = RPC_HT(intern)->rpc_ctor(*(rpc_string *)(class_hash), &(intern->data), num_args, args); intern->data = pool_intern->data;
pefree(pool_intern, TRUE);
retval = SUCCESS;
} else if (RPC_CLASS(intern)->singleton) {
/* singleton */
intern->data = RPC_CLASS(intern)->data;
retval = SUCCESS;
} else {
/* call the rpc ctor */
retval = RPC_HT(intern)->rpc_ctor(*(rpc_string *)(class_hash), &(intern->data), num_args, args);
}
} else { } else {
/* disable caching from now on */ /* disable caching from now on */
intern->hash = NULL; intern->hash = NULL;
@ -712,9 +752,11 @@ ZEND_FUNCTION(rpc_singleton)
GET_INTERNAL_EX(intern, object); GET_INTERNAL_EX(intern, object);
if (!intern->singleton) { if (!RPC_CLASS(intern)) {
intern->singleton = TRUE; /* TODO: exception here, no hashing */
/* TODO: add to instance list */ } else if (!RPC_CLASS(intern)->singleton) {
RPC_CLASS(intern)->singleton = TRUE;
RPC_CLASS(intern)->data = intern->data;
} }
} }
@ -729,9 +771,10 @@ ZEND_FUNCTION(rpc_poolable)
GET_INTERNAL_EX(intern, object); GET_INTERNAL_EX(intern, object);
if (RPC_HT(intern)->poolable && RPC_CLASS(intern) && (RPC_HT(intern)->poolable == TRUE)) {
if (RPC_HT(intern)->poolable == TRUE) { RPC_CLASS(intern)->poolable = TRUE;
intern->poolable = TRUE; } else {
/* TODO: exception here, no hashing */
} }
} }
@ -796,6 +839,79 @@ static void rpc_internal_set(rpc_internal *intern, char *property, zend_uint pro
} }
} }
/***********************************/
static int zend_ts_hash_remove_key_or_index(TsHashTable *ht, char *arKey, uint nKeyLength, void **pData)
{
uint nIndex;
uint h = nKeyLength;
uint result;
void **ppData;
Bucket *p;
tsrm_mutex_lock(ht->mx_writer);
if (arKey) {
result = zend_hash_find(TS_HASH(ht), arKey, nKeyLength, (void **) &ppData);
} else {
result = zend_hash_index_find(TS_HASH(ht), h, (void **) &ppData);
}
if (result == SUCCESS) {
*pData = *ppData;
if (arKey) {
h = zend_inline_hash_func(arKey, nKeyLength);
}
nIndex = h & TS_HASH(ht)->nTableMask;
p = TS_HASH(ht)->arBuckets[nIndex];
while (p != NULL) {
if ((p->h == h) && ((p->nKeyLength == 0) || /* Numeric index */
((p->nKeyLength == nKeyLength) && (!memcmp(p->arKey, arKey, nKeyLength))))) {
HANDLE_BLOCK_INTERRUPTIONS();
if (p == TS_HASH(ht)->arBuckets[nIndex]) {
TS_HASH(ht)->arBuckets[nIndex] = p->pNext;
} else {
p->pLast->pNext = p->pNext;
}
if (p->pNext) {
p->pNext->pLast = p->pLast;
}
if (p->pListLast != NULL) {
p->pListLast->pListNext = p->pListNext;
} else {
/* Deleting the head of the list */
TS_HASH(ht)->pListHead = p->pListNext;
}
if (p->pListNext != NULL) {
p->pListNext->pListLast = p->pListLast;
} else {
TS_HASH(ht)->pListTail = p->pListLast;
}
if (TS_HASH(ht)->pInternalPointer == p) {
TS_HASH(ht)->pInternalPointer = p->pListNext;
}
if (!p->pDataPtr) {
pefree(p->pData, TS_HASH(ht)->persistent);
}
pefree(p, TS_HASH(ht)->persistent);
HANDLE_UNBLOCK_INTERRUPTIONS();
TS_HASH(ht)->nNumOfElements--;
return SUCCESS;
}
p = p->pNext;
}
}
tsrm_mutex_unlock(ht->mx_writer);
return FAILURE;
}
/* /*
* Local variables: * Local variables:
* tab-width: 4 * tab-width: 4

View file

@ -5,7 +5,8 @@
#define HANDLER handler_entries[__handler_counter] #define HANDLER handler_entries[__handler_counter]
#define HANDLER_COUNT (sizeof(handler_entries) / sizeof(rpc_handler_entry)) #define HANDLER_COUNT (sizeof(handler_entries) / sizeof(rpc_handler_entry))
#define RPC_HT(intern) (*(intern->handlers)) #define RPC_HT(intern) (*((intern)->handlers))
#define RPC_CLASS(intern) ((intern)->hash)
#define GET_INTERNAL(intern) rpc_internal *intern; \ #define GET_INTERNAL(intern) rpc_internal *intern; \
if (GET_INTERNAL_EX(intern, object) != SUCCESS) { \ if (GET_INTERNAL_EX(intern, object) != SUCCESS) { \