]> granicus.if.org Git - php/commitdiff
pooling and singleton finally work
authorHarald Radi <phanto@php.net>
Mon, 10 Jun 2002 21:16:25 +0000 (21:16 +0000)
committerHarald Radi <phanto@php.net>
Mon, 10 Jun 2002 21:16:25 +0000 (21:16 +0000)
ext/rpc/handler.h
ext/rpc/php_rpc.h
ext/rpc/rpc.c
ext/rpc/rpc.h

index 81d4fbad8a6ebdbc6616e01cd0de42b6a332b719..e28c9b69e63e9eb567960b2c75e1dd34429a3c86 100644 (file)
@@ -91,22 +91,24 @@ typedef struct _rpc_handler_entry {
 
 /* class/method/function hash */
 typedef struct _rpc_class_hash {
-       rpc_string name; /* must be first entry */
-       TsHashTable methods;
-       TsHashTable properties;
-       zend_class_entry                *ce;
+       rpc_string                      name;           /* must be first entry */
+       zend_bool                       poolable;
+       zend_bool                       singleton;
+       TsHashTable                     methods;
+       TsHashTable                     properties;
+       rpc_object_handlers     **handlers;
+       zend_class_entry        *ce;
+       void                            *data;
 } rpc_class_hash;
 
 /* internal data */
 typedef struct _rpc_internal {
-       zend_bool                               poolable;
-       zend_bool                               singleton;
-       zend_class_entry                *ce;
+       MUTEX_T                                 mx_handler;
+       TsHashTable                             function_table;
        rpc_object_handlers             **handlers;
-       void                                    *data;
        rpc_class_hash                  *hash;
-       TsHashTable                             function_table;
-       MUTEX_T                                 mx_handler;
+       zend_class_entry                *ce;
+       void                                    *data;
 } rpc_internal;
 
 /* proxy data */
index 32074ee70d114918c1718e0aff3364fddde344de..165f3e07ac1270c34c091534bbb8417e4a784ab9 100644 (file)
@@ -29,16 +29,6 @@ ZEND_FUNCTION(rpc_get);
 ZEND_FUNCTION(rpc_singleton);
 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
 
 #endif /* PHP_RPC_H */
\ No newline at end of file
index 04a5f1f02c69fd1efb4e9d583844c14d8c025fd4..eb49110feb76e276b0de7fe5785558e151d1320a 100644 (file)
 #include "rpc.h"
 #include "layer.h"
 
-ZEND_DECLARE_MODULE_GLOBALS(rpc)
-
-static void rpc_globals_ctor(zend_rpc_globals * TSRMLS_DC);
+static void rpc_instance_dtor(void *);
 static void rpc_class_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 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 */
 static zval* rpc_read(zval *, zval *, int  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;
 
 static HashTable *handlers;
+static TsHashTable *pool;
 static TsHashTable *classes;
 static zend_llist *classes_list;
 
@@ -100,10 +100,6 @@ ZEND_GET_MODULE(rpc);
 ZEND_INI_BEGIN()
 ZEND_INI_END()
 
-static void rpc_globals_ctor(zend_rpc_globals *rpc_globals TSRMLS_DC)
-{
-}
-
 /* {{{ ZEND_MINIT_FUNCTION
  */
 ZEND_MINIT_FUNCTION(rpc)
@@ -115,10 +111,12 @@ ZEND_MINIT_FUNCTION(rpc)
        rpc_entry = zend_register_internal_class(&rpc_class_entry TSRMLS_CC);
 
        handlers = (HashTable *) pemalloc(sizeof(HashTable), TRUE);
+       pool = (TsHashTable *) pemalloc(sizeof(TsHashTable), TRUE);
        classes = (TsHashTable *) pemalloc(sizeof(TsHashTable), TRUE);
        classes_list = (zend_llist *) pemalloc(sizeof(zend_llist), 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_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_INIT_MODULE_GLOBALS(rpc, rpc_globals_ctor, NULL);
        REGISTER_INI_ENTRIES();
 
        return SUCCESS;
@@ -153,8 +150,9 @@ ZEND_MINIT_FUNCTION(rpc)
 ZEND_MSHUTDOWN_FUNCTION(rpc)
 {
        /* destroy instances first */
-       zend_ts_hash_destroy(classes);
+       zend_ts_hash_destroy(pool);
 
+       zend_ts_hash_destroy(classes);
        zend_llist_destroy(classes_list);
        zend_hash_destroy(handlers);
 
@@ -184,6 +182,10 @@ static void rpc_class_dtor(void *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)->properties));
 
@@ -201,6 +203,17 @@ static void rpc_string_dtor(void *pDest)
        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)
 {
        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->data = NULL;
-       intern->singleton = FALSE;
-       intern->poolable = FALSE;
        intern->function_table.hash = intern->ce->function_table;
        intern->function_table.reader = 0;
        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);
        {
-               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);
        }
        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)
 {
        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 */
-       pefree(intern, TRUE);
+       } else {
+               RPC_HT(intern)->rpc_dtor(intern->data);
+               pefree(intern, TRUE);
+       }
 }
 
 static zval* rpc_read(zval *object, zval *member, int type TSRMLS_DC)
@@ -479,6 +498,10 @@ ZEND_FUNCTION(rpc_load)
                                        /* set up the cache */
                                        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);
+                                       class_hash->handlers = intern->handlers;
+                                       class_hash->singleton = FALSE;
+                                       class_hash->poolable = FALSE;
+                                       class_hash->data = NULL;
 
                                        /* do hashing */
                                        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);
                        } 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);
+                               /* 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);
                        }
                }
        } else {
@@ -529,6 +552,10 @@ ZEND_FUNCTION(rpc_load)
                        /* set up the cache */
                        class_hash->name.str = NULL;
                        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->properties), 0, NULL, rpc_string_dtor, TRUE);
@@ -549,11 +576,24 @@ ZEND_FUNCTION(rpc_load)
        
        /* if hash function available */
        if (RPC_HT(intern)->rpc_hash) {
+               rpc_internal *pool_intern;
+       
                /* assign cache structure */
-               intern->hash = class_hash;
+               RPC_CLASS(intern) = class_hash;
                
-               /* call the rpc ctor */
-               retval = RPC_HT(intern)->rpc_ctor(*(rpc_string *)(class_hash), &(intern->data), num_args, args);
+               if (zend_ts_hash_remove_key_or_index(pool, RPC_CLASS(intern)->name.str, RPC_CLASS(intern)->name.len + 1, (void **) &pool_intern) == SUCCESS) {
+                       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 {
                /* disable caching from now on */
                intern->hash = NULL;
@@ -712,9 +752,11 @@ ZEND_FUNCTION(rpc_singleton)
 
        GET_INTERNAL_EX(intern, object);
 
-       if (!intern->singleton) {
-               intern->singleton = TRUE;
-               /* TODO: add to instance list */
+       if (!RPC_CLASS(intern)) {
+               /* TODO: exception here, no hashing */
+       } 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);
 
-
-       if (RPC_HT(intern)->poolable == TRUE) {
-               intern->poolable = TRUE;
+       if (RPC_HT(intern)->poolable && RPC_CLASS(intern) && (RPC_HT(intern)->poolable == TRUE)) {
+               RPC_CLASS(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:
  * tab-width: 4
index 092707fa13c5d6109babd6236a64c82de3bbe336..5412544648af867dffa0daef5f80916420f097b2 100644 (file)
@@ -5,7 +5,8 @@
 #define HANDLER handler_entries[__handler_counter]
 #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;                                                           \
                                                                if (GET_INTERNAL_EX(intern, object) != SUCCESS) {       \