Skip to content
This repository has been archived by the owner on Dec 16, 2019. It is now read-only.

Commit

Permalink
Merge pull request #42 from bwoebi/master
Browse files Browse the repository at this point in the history
Implemented what I wanted in #36
  • Loading branch information
krakjoe committed Jan 12, 2013
2 parents cac52a9 + 6afcd73 commit 6aa99d4
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 16 deletions.
62 changes: 48 additions & 14 deletions src/store.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ typedef struct _pthreads_storage {
/* {{{ statics */
static pthreads_storage pthreads_store_create(zval *pzval, zend_bool complex TSRMLS_DC);
static int pthreads_store_convert(pthreads_storage storage, zval *pzval TSRMLS_DC);
static int pthreads_store_tostring(zval *pzval, char **pstring, size_t *slength TSRMLS_DC);
static int pthreads_store_tostring(zval *pzval, char **pstring, size_t *slength, zend_bool complex TSRMLS_DC);
static int pthreads_store_tozval(zval *pzval, char *pstring, size_t slength TSRMLS_DC);
static void pthreads_store_storage_dtor (pthreads_storage *element);
static void pthreads_store_event_dtor (pthreads_synchro *element);
Expand Down Expand Up @@ -255,12 +255,51 @@ void pthreads_store_free(pthreads_store store TSRMLS_DC){
}
} /* }}} */

/* {{{ set ressources to NULL for non-complex types; helper-function for pthreads_remove_obj_arr_recursive_ressources */
void pthreads_remove_obj_arr_ressources(zval **pzval TSRMLS_DC) {
if (Z_TYPE_PP(pzval) == IS_RESOURCE) {
Z_TYPE_PP(pzval) = IS_NULL;
}
pthreads_remove_obj_arr_recursive_ressources(pzval TSRMLS_CC);
} /* }}} */

/* {{{ set corrupt objects (like mysqli after thread duplication) to NULL and recurse */
void pthreads_remove_obj_arr_recursive_ressources(zval **pzval TSRMLS_DC) {
int is_temp;

HashTable *thash = NULL;
switch (Z_TYPE_PP(pzval)) {
case IS_ARRAY:
thash = Z_ARRVAL_PP(pzval);

case IS_OBJECT:
if (thash == NULL) {
zend_object *zobj = Z_OBJ_P(*pzval);
if (zobj == 0) { // something that haven't been stored...
GC_REMOVE_ZVAL_FROM_BUFFER(*pzval);
Z_TYPE_PP(pzval) = IS_NULL;
return;
}
thash = Z_OBJDEBUG_PP(pzval, is_temp);
}

if (thash) {
zend_hash_apply(thash, (apply_func_args_t)pthreads_remove_obj_arr_ressources TSRMLS_CC);
}

break;
}
} /* }}} */

/* {{{ zval to string */
static int pthreads_store_tostring(zval *pzval, char **pstring, size_t *slength TSRMLS_DC) {
static int pthreads_store_tostring(zval *pzval, char **pstring, size_t *slength, zend_bool complex TSRMLS_DC) {
int result = FAILURE;
if (pzval && (Z_TYPE_P(pzval) != IS_OBJECT || Z_OBJ_P(pzval))) {
if (pzval && (Z_TYPE_P(pzval) != IS_OBJECT || Z_OBJ_P(pzval))) {
if (!complex && (Z_TYPE_P(pzval) == IS_OBJECT || Z_TYPE_P(pzval) == IS_ARRAY)) {
pthreads_remove_obj_arr_recursive_ressources(&pzval TSRMLS_CC);
}
smart_str *psmart = (smart_str*) calloc(1, sizeof(smart_str));
if (psmart) {
if (psmart) {
php_serialize_data_t vars;
PHP_VAR_SERIALIZE_INIT(vars);
php_var_serialize(
Expand Down Expand Up @@ -372,16 +411,11 @@ static pthreads_storage pthreads_store_create(zval *unstore, zend_bool complex T

case IS_OBJECT:
case IS_ARRAY: {
if (complex) {
if (pthreads_store_tostring(unstore, (char**) &storage->data, &storage->length TSRMLS_CC)==SUCCESS) {
if (storage->type==IS_ARRAY) {
storage->exists = zend_hash_num_elements(Z_ARRVAL_P(unstore));
} else storage->exists = 1;
} else free(storage);
} else {
storage->exists = 0;
storage->type = IS_NULL;
}
if (pthreads_store_tostring(unstore, (char**) &storage->data, &storage->length, complex TSRMLS_CC)==SUCCESS) {
if (storage->type==IS_ARRAY) {
storage->exists = zend_hash_num_elements(Z_ARRVAL_P(unstore));
} else storage->exists = 1;
} else free(storage);
} break;

default: storage->exists = 0;
Expand Down
3 changes: 3 additions & 0 deletions src/store.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ int pthreads_store_write(pthreads_store store, char *key, int keyl, zval **write
/* {{{ separate a zval using internals */
int pthreads_store_separate(zval * pzval, zval **seperated, zend_bool allocate, zend_bool complex TSRMLS_DC); /* }}} */

/* {{{ remove ressources if not complex */
void pthreads_remove_obj_arr_recursive_ressources(zval **pzval TSRMLS_DC); /* }}} */

/* {{{ free buffers */
void pthreads_store_free(pthreads_store store TSRMLS_DC); /* }}} */
#endif
67 changes: 67 additions & 0 deletions tests/complex-statics-set-null.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
--TEST--
Test NULLing ressources in arrays
--FILE--
<?php
class file {
public static $fps;

public static function __callstatic($method, $args) {
$tid = Thread::getThreadId();
if (isset(self::$fps[$tid])) {
return call_user_func_array(array("file", "_{$method}"), array_merge($args, array($tid)));
} else {
self::$fps[$tid] = fopen(__FILE__, "r+");
if (isset(self::$fps[$tid]))
return call_user_func_array(array("file", "_{$method}"), array_merge($args, array($tid)));
}
}

public static function _get ($arg, $tid) {
printf("%s: %s\n", __METHOD__, $arg);
var_dump(self::$fps);
}
}

class UserThread extends Thread {
public function run () {
/* execute calls */
$i = 2;
file::get("something".(++$i));
file::get("something".(++$i));

}
}

$i = 0;

file::get("something".(++$i));
file::get("something".(++$i));

$thread = new UserThread();
$thread->start();
?>
--EXPECTF--
file::_get: something1
array(1) {
[%i]=>
resource(5) of type (stream)
}
file::_get: something2
array(1) {
[%i]=>
resource(5) of type (stream)
}
file::_get: something3
array(2) {
[%i]=>
NULL
[%i]=>
resource(2) of type (stream)
}
file::_get: something4
array(2) {
[%i]=>
NULL
[%i]=>
resource(2) of type (stream)
}
4 changes: 2 additions & 2 deletions tests/complex-statics.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ class sql {

public static function __callstatic($method, $args){
$tid = Thread::getThreadId();
if (self::$connection[$tid]) {
if (isset(self::$connection[$tid])) {
return call_user_func_array(array(self::$connection[$tid], "_{$method}"), $args);
} else {
self::$connection[$tid] = new sql();
if (self::$connection[$tid])
if (isset(self::$connection[$tid]))
return call_user_func_array(array(self::$connection[$tid], "_{$method}"), $args);
}
}
Expand Down

0 comments on commit 6aa99d4

Please sign in to comment.