]> granicus.if.org Git - php/commitdiff
pass function signature in zend_parse_parameters style
authorHarald Radi <phanto@php.net>
Tue, 19 Mar 2002 23:28:52 +0000 (23:28 +0000)
committerHarald Radi <phanto@php.net>
Tue, 19 Mar 2002 23:28:52 +0000 (23:28 +0000)
lookup cache works now per signature (not only method name)
reviewed resource management
# have to learn now ..

ext/rpc/com/com.c
ext/rpc/handler.h
ext/rpc/rpc.c
ext/rpc/rpc.h
ext/rpc/tests/test1.php

index 0ccccfe3b8f55017a60f7f7fcb9b31b1ae3dbf6c..522be7dcd101cbba07b8399130cd2ca4ec58a3fb 100644 (file)
@@ -1,7 +1,7 @@
 #include "com.h"
 
 /* protos */
-static int com_hash(char *, zend_uint, char **, zend_uint *, int, zval ***, int);
+static int com_hash(char *, zend_uint, char **, zend_uint *, int, char *, int);
 static int com_ctor(char *, zend_uint, void **, int , zval ***);
 static int com_dtor(void **);
 static int com_call(char *, zend_uint, void **, zval **, int, zval ***);
@@ -17,7 +17,7 @@ static int com_get_properties(HashTable **, void **);
 /* register rpc callback function */
 RPC_REGISTER_HANDLERS_START(com)
 POOL,
-HASH_AS_INT,
+HASH_AS_INT_WITH_SIGNATURE,
 com_hash,
 com_ctor,
 com_dtor,
@@ -51,7 +51,7 @@ RPC_INIT_FUNCTION(com)
 
 /* rpc handler functions */
 
-static int com_hash(char *name, zend_uint name_len, char **hash, zend_uint *hash_len, int num_args, zval **args[], int type)
+static int com_hash(char *name, zend_uint name_len, char **hash, zend_uint *hash_len, int num_args, char *arg_types, int type)
 {
        *hash = strdup(name);
        *hash_len = name_len;
index bc3e9b34d29bda950ab6a34378e52977d66ccafa..3b108d57548c7a4c1101c071d5b91e160c6f44b3 100644 (file)
@@ -56,7 +56,7 @@
 typedef struct _rpc_object_handlers {
        const zend_bool pool_instances;
        const zend_uint hash_type;
-       int (*rpc_hash)(char *name, zend_uint name_len, char **hash, zend_uint *hash_len, int num_args, zval **args[], int type);
+       int (*rpc_hash)(char *name, zend_uint name_len, char **hash, zend_uint *hash_len, int num_args, char *arg_types, int type);
        int (*rpc_ctor)(char *class_name, zend_uint class_name_len, void **data, int num_args, zval **args[]);
        int (*rpc_dtor)(void **data);
        int (*rpc_call)(char *method_name, zend_uint method_name_len, void **data, zval **return_value, int num_args, zval **args[]);
index 2652ff6ce35e69fbb39a29ef279c0362a44790f0..7c63ab7a3c120cb68121a4e67f14cef598a6382e 100644 (file)
@@ -85,6 +85,7 @@ zend_module_entry rpc_module_entry = {
 static HashTable *handlers;
 static WormHashTable *instance;
 static WormHashTable *classes;
+static zend_llist *classes_list;
 
 #ifdef COMPILE_DL_RPC
 ZEND_GET_MODULE(rpc);
@@ -108,11 +109,13 @@ ZEND_MINIT_FUNCTION(rpc)
        handlers = (HashTable *) pemalloc(sizeof(HashTable), TRUE);
        instance = (WormHashTable *) pemalloc(sizeof(WormHashTable), TRUE);
        classes = (WormHashTable *) pemalloc(sizeof(WormHashTable), TRUE);
+       classes_list = (zend_llist *) pemalloc(sizeof(zend_llist), TRUE);
 
        zend_hash_init(handlers, 0, NULL, NULL, TRUE);  
        zend_worm_hash_init(instance, 0, NULL, rpc_instance_dtor, TRUE);
-       zend_worm_hash_init(classes, 0, NULL, rpc_class_dtor, TRUE);
-       
+       zend_worm_hash_init(classes, 0, NULL, NULL, TRUE);
+       zend_llist_init(classes_list, sizeof(rpc_class_hash **), rpc_class_dtor, TRUE);
+
        FOREACH_HANDLER {
                HANDLER.rpc_handler_init();
                
@@ -145,10 +148,11 @@ ZEND_MINIT_FUNCTION(rpc)
  */
 ZEND_MSHUTDOWN_FUNCTION(rpc)
 {
+       /* destroy instances first */
        zend_worm_hash_destroy(instance);
        zend_worm_hash_destroy(classes);
 
-       /* destroy instances first ! */
+       zend_llist_destroy(classes_list);
        zend_hash_destroy(handlers);
 
        pefree(handlers, TRUE);
@@ -197,7 +201,7 @@ static void rpc_class_dtor(void *pDest)
        zend_worm_hash_destroy(&((*hash)->properties));
 
        free((*hash)->name.str);
-       pefree(*hash, TRUE);
+       pefree((*hash), TRUE);
 }
 
 static void rpc_string_dtor(void *pDest)
@@ -436,7 +440,9 @@ ZEND_FUNCTION(rpc_load)
        rpc_class_hash *class_hash;
        rpc_class_hash **class_hash_find = NULL;
        rpc_internal **intern;
-       int retval;
+       rpc_string hash_val;
+       int retval, append = 0;
+       char *arg_types;
 
        /* check if we were called as a constructor or as a function */
        if (!object) {
@@ -463,7 +469,7 @@ ZEND_FUNCTION(rpc_load)
        }
 
        /* fetch further parameters */
-       GET_ARGS_EX(num_args, args, args_free, 2);
+       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", &((*intern)->class_name_len)) != SUCCESS) ||
@@ -481,26 +487,31 @@ ZEND_FUNCTION(rpc_load)
                        /* hash classname if hashing function exists */
                        if ((*(*intern)->handlers)->rpc_hash) {
 
+                               GET_CTOR_SIGNATURE(intern, hash_val, num_args, arg_types);
+
                                /* check if already hashed */   
-                               if (zend_worm_hash_find(classes, (*intern)->class_name, (*intern)->class_name_len + 1, (void **) &class_hash_find) != SUCCESS) {
+                               if (zend_worm_hash_find(classes, hash_val.str, hash_val.len + 1, (void **) &class_hash_find) != SUCCESS) {
                                        class_hash = pemalloc(sizeof(rpc_class_hash), TRUE);
 
                                        /* set up the cache */
                                        zend_worm_hash_init(&(class_hash->methods), 0, NULL, rpc_string_dtor, TRUE);
                                        zend_worm_hash_init(&(class_hash->properties), 0, NULL, rpc_string_dtor, TRUE);
 
-                                       if ((*(*intern)->handlers)->hash_type & HASH_WITH_SIGNATURE) {
-                                               /* TODO: add signature to hash key */
-                                       }
 
                                        /* do hashing */
                                        if ((*(*intern)->handlers)->rpc_hash((*intern)->class_name, (*intern)->class_name_len, &(class_hash->name.str),
-                                                                                                                &(class_hash->name.len), num_args, args, CLASS) != SUCCESS) {
+                                                                                                                &(class_hash->name.len), num_args, arg_types, CLASS) != SUCCESS) {
                                                /* TODO: exception */
                                        }
 
-                                       /* register with non-hashed key */
-                                       zend_worm_hash_add(classes, (*intern)->class_name, (*intern)->class_name_len + 1, &class_hash, sizeof(rpc_class_hash *), NULL);
+                                       /* 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
+                                        */
+                                       zend_worm_hash_add(classes, hash_val.str, hash_val.len + 1, &class_hash, sizeof(rpc_class_hash *), (void **) &class_hash_find);
+                                       tsrm_mutex_lock(classes->mx_writer);
+                                       zend_llist_add_element(classes_list, class_hash_find);
+                                       tsrm_mutex_unlock(classes->mx_writer);
 
                                        if (class_hash->name.str) {
                                                /* register string hashcode */
@@ -512,6 +523,8 @@ ZEND_FUNCTION(rpc_load)
                                } else {
                                        class_hash = *class_hash_find;
                                }
+
+                               FREE_SIGNATURE(hash_val, arg_types);
                        }
                }
        } else {
@@ -526,10 +539,6 @@ ZEND_FUNCTION(rpc_load)
                        zend_worm_hash_init(&(class_hash->methods), 0, NULL, rpc_string_dtor, TRUE);
                        zend_worm_hash_init(&(class_hash->properties), 0, NULL, rpc_string_dtor, TRUE);
 
-                       if ((*(*intern)->handlers)->hash_type & HASH_WITH_SIGNATURE) {
-                               /* TODO: add signature to hash key */
-                       }
-
                        /* register int hashcode, we don't know more */
                        zend_worm_hash_index_update(classes, class_hash->name.len, &class_hash, sizeof(rpc_class_hash *), NULL);
                } else {
@@ -564,7 +573,7 @@ ZEND_FUNCTION(rpc_call)
        zval *object = getThis();
        zval ***args, ***args_free;
        zend_uint num_args = ZEND_NUM_ARGS(); 
-       char *hash = NULL;
+       char *hash = NULL, *arg_types;
        int hash_len, retval, strip = 0;
 
        /* check if we were called as a method or as a function */
@@ -592,7 +601,7 @@ ZEND_FUNCTION(rpc_call)
        
        /* scope for internal data */
        {
-               rpc_string *method_hash, **method_hash_find;
+               rpc_string hash_val, *method_hash, **method_hash_find;
                GET_INTERNAL(intern);
 
                method_hash = (rpc_string *) pemalloc(sizeof(rpc_string), TRUE);
@@ -602,28 +611,27 @@ ZEND_FUNCTION(rpc_call)
                if ((*intern)->hash) {
                        /* cache method table lookups */
                
-                       if ((*(*intern)->handlers)->hash_type & HASH_WITH_SIGNATURE) {
-                               /* TODO: add signature to hash key */
-                       }
-
                        if (!hash && !((*(*intern)->handlers)->hash_type & HASH_AS_INT)) {
                                /* TODO: exception */
                        } else if(hash) {
-                               /* string method */
+                               /* string passed */
+                               GET_METHOD_SIGNATURE(intern, method_hash, hash_val, num_args, arg_types);
 
                                /* check if already hashed */   
-                               if (zend_worm_hash_find(&((*intern)->hash->methods), hash, hash_len + 1, (void **) &method_hash_find) != SUCCESS) {
+                               if (zend_worm_hash_find(&((*intern)->hash->methods), hash_val.str, hash_val.len + 1, (void **) &method_hash_find) != SUCCESS) {
                                        if ((*(*intern)->handlers)->rpc_hash(hash, hash_len, &(method_hash->str), &(method_hash->len),
-                                                                                                                num_args, args, METHOD) != SUCCESS) {
+                                                                                                                num_args, arg_types, METHOD) != SUCCESS) {
                                                /* TODO: exception */
                                        }
 
                                        /* register with non-hashed key */
-                                       zend_worm_hash_add(&((*intern)->hash->methods), hash, hash_len + 1, &method_hash, sizeof(rpc_string *), NULL);
+                                       zend_worm_hash_add(&((*intern)->hash->methods), hash_val.str, hash_val.len + 1, &method_hash, sizeof(rpc_string *), NULL);
                                } else {
                                        pefree(method_hash, TRUE);
                                        method_hash = *method_hash_find;
                                }
+
+                               FREE_SIGNATURE(hash_val, arg_types);
                        }
                }
 
index 81f8af314a3f095a502a5806c8a491478e193466..ce2b0e59d61f7721cc70edacd4d0eddace7f6d48 100644 (file)
                                                        /* TODO: exception */                                                                                   \
                                                }
 
+#define GET_CTOR_SIGNATURE(intern, hash_val, num_args, arg_types)                                                                                                      \
+                       GET_SIGNATURE(intern, (*intern)->class_name, (*intern)->class_name_len, hash_val, num_args, arg_types)
+
+#define GET_METHOD_SIGNATURE(intern, method, hash_val, num_args, arg_types)                                                                                    \
+                       GET_SIGNATURE(intern, method->str, method->len, hash_val, num_args, arg_types)
+
+#define GET_SIGNATURE(intern, name, name_len, hash_val, num_args, arg_types)                                                                           \
+                                               hash_val.len = name_len;                                                                                                                                        \
+                                                                                                                                                                                                                                       \
+                                               if ((*(*intern)->handlers)->hash_type & HASH_WITH_SIGNATURE) {                                                          \
+                                                       zend_uint _signature_counter;                                                                                                                   \
+                                                                                                                                                                                                                                       \
+                                                       arg_types = (char *) emalloc(sizeof(char) * (num_args + 1));                                                    \
+                                                       hash_val.len += num_args + 1;                                                                                                                   \
+                                                                                                                                                                                                                                       \
+                                                       for (_signature_counter = 0; _signature_counter < num_args; _signature_counter++) {             \
+                                                               switch (Z_TYPE_PP(args[_signature_counter])) {                                                                          \
+                                                                       case IS_NULL:                                                                                                                                   \
+                                                                               arg_types[_signature_counter] = 'n';                                                                            \
+                                                                               break;                                                                                                                                          \
+                                                                       case IS_LONG:                                                                                                                                   \
+                                                                               arg_types[_signature_counter] = 'l';                                                                            \
+                                                                               break;                                                                                                                                          \
+                                                                       case IS_DOUBLE:                                                                                                                                 \
+                                                                               arg_types[_signature_counter] = 'd';                                                                            \
+                                                                               break;                                                                                                                                          \
+                                                                       case IS_STRING:                                                                                                                                 \
+                                                                               arg_types[_signature_counter] = 's';                                                                            \
+                                                                               break;                                                                                                                                          \
+                                                                       case IS_ARRAY:                                                                                                                                  \
+                                                                               arg_types[_signature_counter] = 'a';                                                                            \
+                                                                               break;                                                                                                                                          \
+                                                                       case IS_OBJECT:                                                                                                                                 \
+                                                                               arg_types[_signature_counter] = 'o';                                                                            \
+                                                                               break;                                                                                                                                          \
+                                                                       case IS_BOOL:                                                                                                                                   \
+                                                                               arg_types[_signature_counter] = 'b';                                                                            \
+                                                                               break;                                                                                                                                          \
+                                                                       case IS_RESOURCE:                                                                                                                               \
+                                                                               arg_types[_signature_counter] = 'r';                                                                            \
+                                                                               break;                                                                                                                                          \
+                                                                       default:                                                                                                                                                \
+                                                                               arg_types[_signature_counter] = 'u';                                                                            \
+                                                               }                                                                                                                                                                       \
+                                                       }                                                                                                                                                                               \
+                                                                                                                                                                                                                                       \
+                                                       arg_types[_signature_counter] = '\0';                                                                                                   \
+                                               } else {                                                                                                                                                                        \
+                                                       arg_types = (char *) emalloc(sizeof(char));                                                                                             \
+                                                       arg_types[0] = '\0';                                                                                                                                    \
+                                               }                                                                                                                                                                                       \
+                                                                                                                                                                                                                                       \
+                                               hash_val.str = (char *) emalloc(sizeof(char) * (hash_val.len + 2));                                                     \
+                                               memcpy(hash_val.str, arg_types, num_args + 1);                                                                                          \
+                                               memcpy(&hash_val.str[hash_val.len - name_len],                                                                                          \
+                                                          name, name_len + 1);
+
+#define FREE_SIGNATURE(hash_val, arg_types)                                                                                                                                                    \
+                                               efree(arg_types);                                                                                                                                                       \
+                                               efree(hash_val.str);
+
+
+
 #define RPC_REFCOUNT(intern) ((*intern)->refcount)
 #define RPC_ADDREF(intern) (++RPC_REFCOUNT(intern))
 #define RPC_DELREF(intern) (--RPC_REFCOUNT(intern))
index e989f53168530c477aef056ccf752ee3aecf364b..aee876aedb3cfbb25b600be6752ba17cf4152c84 100644 (file)
@@ -1,11 +1,26 @@
 <?php
 print "huhuhdsa";
 
-$rpc = new com("class", true);
-$rpc2 = new com("class", true, "hehe", 12);
+$rpc = new com("class", true, "huh");
+$rpc2 = new com("class", true, "hehe", 1);
 $rpc->call("blah");
 $rpc->call("heh");
+$rpc->call("blah");
+com_call($rpc, 1, "1");
+com_call($rpc, 1, "1");
+$rpc->call("blah");
+$rpc->call("blah");
+$rpc->call("blah");
+$rpc2->call("hehe");
+$rpc2->call("hehe");
+$rpc2->call("hehe");
+$rpc2->call("hehe");
+$rpc2->call("hehe");
+com_call($rpc, "call", 1);
+com_call($rpc, 1, "1");
 com_call($rpc, "call", 1);
+com_call($rpc2, "call", 1);
+com_call($rpc2, "call", 1);
 //$rpc->addref();
 
 //$clone = $rpc->__clone();
@@ -18,7 +33,7 @@ com_call($rpc, "call", 1);
 //delete $rpc;
 //delete $clone;
 
-$heh = com_load(1, 1);
+$heh = com_load("heh", 1);
 $heh->knorp();
 /*delete $heh;*/
 ?>
\ No newline at end of file