|
42 | 42 |
|
43 | 43 | #define R_SUB_CALLBACK_CLASS_TYPE 1 |
44 | 44 | #define R_SUB_CALLBACK_FT_TYPE 2 |
| 45 | +#define R_SUB_CLOSURE_TYPE 3 |
45 | 46 |
|
46 | 47 | int le_redis_sock; |
47 | 48 | extern int le_redis_array; |
@@ -5278,21 +5279,23 @@ PHP_METHOD(Redis, publish) |
5278 | 5279 |
|
5279 | 5280 | PHPAPI void generic_subscribe_cmd(INTERNAL_FUNCTION_PARAMETERS, char *sub_cmd) |
5280 | 5281 | { |
5281 | | - zval *z_callback,*object, *array, **data; |
| 5282 | + zval *object, *array, **data; |
5282 | 5283 | HashTable *arr_hash; |
5283 | 5284 | HashPosition pointer; |
5284 | 5285 | RedisSock *redis_sock; |
5285 | | - char *cmd = "", *old_cmd = NULL, *callback_ft_name; |
5286 | | - int cmd_len, array_count, callback_ft_name_len; |
| 5286 | + char *cmd = "", *old_cmd = NULL; |
| 5287 | + int cmd_len, array_count; |
5287 | 5288 | zval *z_tab, **tmp; |
5288 | 5289 | char *type_response; |
5289 | 5290 |
|
5290 | | - int callback_type = 0; |
5291 | | - zval *z_o, *z_fun = NULL,*z_ret, *z_args[4]; |
5292 | | - char *method_name; |
| 5291 | + // Function call information |
| 5292 | + zend_fcall_info z_callback; |
| 5293 | + zend_fcall_info_cache z_callback_cache; |
| 5294 | + |
| 5295 | + zval *z_ret, **z_args[4]; |
5293 | 5296 |
|
5294 | | - if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oaz|z", |
5295 | | - &object, redis_ce, &array, &z_callback) == FAILURE) { |
| 5297 | + if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oaf", |
| 5298 | + &object, redis_ce, &array, &z_callback, &z_callback_cache) == FAILURE) { |
5296 | 5299 | RETURN_FALSE; |
5297 | 5300 | } |
5298 | 5301 |
|
@@ -5352,32 +5355,10 @@ PHPAPI void generic_subscribe_cmd(INTERNAL_FUNCTION_PARAMETERS, char *sub_cmd) |
5352 | 5355 | } |
5353 | 5356 | efree(z_tab); |
5354 | 5357 |
|
5355 | | - /* verify the callback */ |
5356 | | - if(Z_TYPE_P(z_callback) == IS_ARRAY) { |
5357 | | - |
5358 | | - /* object */ |
5359 | | - if (zend_hash_index_find(Z_ARRVAL_P(z_callback), 0, (void**)&tmp) == FAILURE) { |
5360 | | - RETURN_FALSE; |
5361 | | - } |
5362 | | - z_o = *tmp; |
5363 | | - |
5364 | | - /* method name */ |
5365 | | - if (zend_hash_index_find(Z_ARRVAL_P(z_callback), 1, (void**)&tmp) == FAILURE) { |
5366 | | - RETURN_FALSE; |
5367 | | - } |
5368 | | - method_name = Z_STRVAL_PP(tmp); |
5369 | | - |
5370 | | - ALLOC_INIT_ZVAL(z_fun); |
5371 | | - ZVAL_STRING(z_fun, method_name, 1); |
5372 | | - callback_type = R_SUB_CALLBACK_CLASS_TYPE; |
5373 | | - |
5374 | | - } else if(Z_TYPE_P(z_callback) == IS_STRING) { |
5375 | | - callback_ft_name = Z_STRVAL_P(z_callback); |
5376 | | - callback_ft_name_len = strlen(callback_ft_name); |
5377 | | - callback_type = R_SUB_CALLBACK_FT_TYPE; |
5378 | | - MAKE_STD_ZVAL(z_fun); |
5379 | | - ZVAL_STRINGL(z_fun, callback_ft_name, callback_ft_name_len, 0); |
5380 | | - } |
| 5358 | + // Set a pointer to our return value and to our arguments. |
| 5359 | + z_callback.retval_ptr_ptr = &z_ret; |
| 5360 | + z_callback.params = z_args; |
| 5361 | + z_callback.no_separation = 0; |
5381 | 5362 |
|
5382 | 5363 | /* Multibulk Response, format : {message type, originating channel, message payload} */ |
5383 | 5364 | while(1) { |
@@ -5420,48 +5401,43 @@ PHPAPI void generic_subscribe_cmd(INTERNAL_FUNCTION_PARAMETERS, char *sub_cmd) |
5420 | 5401 | } |
5421 | 5402 |
|
5422 | 5403 | // Always pass the Redis object through |
5423 | | - z_args[0] = getThis(); |
| 5404 | + z_args[0] = &getThis(); |
5424 | 5405 |
|
5425 | 5406 | // Set up our callback args depending on the message type |
5426 | 5407 | if(is_pmsg) { |
5427 | | - z_args[1] = *pattern; |
5428 | | - z_args[2] = *channel; |
5429 | | - z_args[3] = *data; |
| 5408 | + z_args[1] = pattern; |
| 5409 | + z_args[2] = channel; |
| 5410 | + z_args[3] = data; |
5430 | 5411 | } else { |
5431 | | - z_args[1] = *channel; |
5432 | | - z_args[2] = *data; |
| 5412 | + z_args[1] = channel; |
| 5413 | + z_args[2] = data; |
5433 | 5414 | } |
5434 | | - |
5435 | | - switch(callback_type) { |
5436 | | - case R_SUB_CALLBACK_CLASS_TYPE: |
5437 | | - MAKE_STD_ZVAL(z_ret); |
5438 | | - call_user_function(&redis_ce->function_table, &z_o, z_fun, z_ret, tab_idx, z_args TSRMLS_CC); |
5439 | | - efree(z_ret); |
5440 | | - break; |
5441 | 5415 |
|
5442 | | - case R_SUB_CALLBACK_FT_TYPE: |
5443 | | - MAKE_STD_ZVAL(z_ret); |
5444 | | - call_user_function(EG(function_table), NULL, z_fun, z_ret, tab_idx, z_args TSRMLS_CC); |
5445 | | - efree(z_ret); |
5446 | | - break; |
| 5416 | + // Set our argument information |
| 5417 | + z_callback.param_count = tab_idx; |
| 5418 | + |
| 5419 | + // Break if we can't call the function |
| 5420 | + if(zend_call_function(&z_callback, &z_callback_cache TSRMLS_CC) != SUCCESS) { |
| 5421 | + break; |
5447 | 5422 | } |
| 5423 | + |
| 5424 | + // If we have a return value, free it. Note, we could use the return value to break the subscribe loop |
| 5425 | + if(z_ret) zval_ptr_dtor(&z_ret); |
| 5426 | + |
5448 | 5427 | /* TODO: provide a way to break out of the loop. */ |
5449 | 5428 | zval_dtor(z_tab); |
5450 | 5429 | efree(z_tab); |
5451 | 5430 | } |
5452 | | - |
5453 | | - // Free our function |
5454 | | - efree(z_fun); |
5455 | 5431 | } |
5456 | 5432 |
|
5457 | | -/* {{{ proto void Redis::psubscribe(Array(channel1, channel2, ... channelN)) |
| 5433 | +/* {{{ proto void Redis::psubscribe(Array(pattern1, pattern2, ... patternN)) |
5458 | 5434 | */ |
5459 | 5435 | PHP_METHOD(Redis, psubscribe) |
5460 | 5436 | { |
5461 | 5437 | generic_subscribe_cmd(INTERNAL_FUNCTION_PARAM_PASSTHRU, "psubscribe"); |
5462 | 5438 | } |
5463 | 5439 |
|
5464 | | -/* {{{ proto void Redis::psubscribe(Array(channel1, channel2, ... channelN)) |
| 5440 | +/* {{{ proto void Redis::subscribe(Array(channel1, channel2, ... channelN)) |
5465 | 5441 | */ |
5466 | 5442 | PHP_METHOD(Redis, subscribe) { |
5467 | 5443 | generic_subscribe_cmd(INTERNAL_FUNCTION_PARAM_PASSTHRU, "subscribe"); |
|
0 commit comments