|
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