摘要:起步很多時候,需要把控制權限交給用戶,或者在擴展里完成某件事后去回調用戶的方法。在擴展里是通過函數來調用用戶空間的函數的。收集回調函數的返回值。回調函數需要傳遞參數的個數。利用語言多線程庫來實現一個簡單的并行擴展。
起步
很多時候,需要把控制權限交給用戶,或者在擴展里完成某件事后去回調用戶的方法。
在PHP擴展里是通過 call_user_function_ex 函數來調用用戶空間的函數的。
定義它的定義在 Zend/zend_API.h :
#define call_user_function_ex(function_table, object, function_name, retval_ptr, param_count, params, no_separation, symbol_table) _call_user_function_ex(object, function_name, retval_ptr, param_count, params, no_separation)
通過宏定義替換為_call_user_function_ex,其中參數 function_table 被移除了,它之所以在API才存在大概是為了兼容以前的寫法。函數的真正定義是:
ZEND_API int _call_user_function_ex( zval *object, zval *function_name, zval *retval_ptr, uint32_t param_count, zval params[], int no_separation);
參數分析:
zval *object:這個是用來我們調用類里的某個方法的對象。
zval *function_name:要調用的函數的名字。
zval *retval_ptr:收集回調函數的返回值。
uint32_t param_count:回調函數需要傳遞參數的個數。
zval params[]: 參數列表。
int no_separation:是否對zval進行分離,如果設為1則直接會出錯,分離的作用是為了優化空間。
回調功能的實現PHP_FUNCTION(hello_callback) { zval *function_name; zval retval; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &function_name) == FAILURE) { return; } if (Z_TYPE_P(function_name) != IS_STRING) { php_printf("Function require string argumnets!"); return; } //TSRMLS_FETCH(); if (call_user_function_ex(EG(function_table), NULL, function_name, &retval, 0, NULL, 0, NULL TSRMLS_CC) != SUCCESS) { php_printf("Function call failed!"); return; } *return_value = retval; zval_copy_ctor(return_value); zval_ptr_dtor(&retval); }
zval_copy_ctor()原始(zval)的內容拷貝給它。zval_ptr_dtor()釋放空間。return_value不是一個函數外的變量,它的由函數聲明里的變量。PHP_FUNCTION(hello_callback)這個聲明是簡寫,最終會被預處理宏替換為:
void zif_hello_callback(zend_execute_data *execute_data, zval *return_value)
return_value變量其實也就是最終返回給調用腳本的,RETURN_STR(s) 等返回函數最終也都是宏替換為對該變量的操作。
測試腳本:
一個并行擴展早期的php不支持多進程多線程的,現在隨著發展有很多擴展不斷完善它,諸如pthread,swoole等,不僅能多線程,而且能實現異步。
利用c語言多線程pthread庫來實現一個簡單的并行擴展。
先聲明我們一會用到的結構:
struct myarg { zval *fun; zval ret; };線程函數:
static void my_thread(struct myarg *arg) { zval *fun = arg->fun; zval ret = arg->ret; if (call_user_function_ex(EG(function_table), NULL, fun, &ret, 0, NULL, 0, NULL TSRMLS_CC) != SUCCESS) { return; } }函數的實現:
PHP_FUNCTION(hello_thread) { pthread_t tid; zval *fun1, *fun2; zval ret1, ret2; struct myarg arg; int ret; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &fun1, &fun2) == FAILURE) { return; } arg.fun = fun1; arg.ret = ret1; ret = pthread_create(&tid, NULL, (void*)my_thread, (void*)&arg); if(ret != 0) { php_printf("Thread Create Error "); exit(0); } if (call_user_function_ex(EG(function_table), NULL, fun2, &ret2, 0, NULL, 0, NULL TSRMLS_CC) != SUCCESS) { return; } pthread_join(tid, NULL); RETURN_NULL(); }測試腳本:
輸出:
兩次的輸出結果不一樣,并且echo "after 多并發";是在兩個函數都運行完后才執行的。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/22092.html
摘要:但在密集計算方面比等靜態編譯語言差幾十倍甚至上百倍。一使用棧內存在引擎和擴展中,經常要創建一個的變量,底層就是一個指針。代碼中創建的變量也進行了優化,直接在棧內存上預分配。應用層與底層在錯誤拋出的方式全部統一為異常。 原文:http://rango.swoole.com/archives/440最近PHP官方終于發布了傳說中的PHP7,雖然只是alpha版。PHP7號稱是新一代的PHP...
摘要:目前來看等語言還難以企及和。作為一個資深的開發者,在技術上給各位程序十點未來的建議,希望對大家有所幫助。開發者應當學習掌握規范,在開發程序時應當盡量遵循規范。程序員除了寫后臺程序之外,還有很大一部分工作在展現層,和瀏覽器前端打交道。 PHP 從誕生到現在已經有20多年歷史,從Web時代興起到移動互聯網退潮,互聯網領域各種編程語言和技術層出不窮, Node.js 、 GO 、 Pytho...
摘要:修復添加超過萬個以上定時器時發生崩潰的問題增加模塊,下高性能序列化庫修復監聽端口設置無效的問題等。線程來處理網絡事件輪詢,讀取數據。當的三次握手成功了以后,由這個線程將連接成功的消息告訴進程,再由進程轉交給進程。此時進程觸發事件。 本文示例代碼詳見:https://github.com/52fhy/swoo...。 簡介 Swoole是一個PHP擴展,提供了PHP語言的異步多線程服務器...
摘要:我們為了處理這些挑戰,提出了一個新的引用測試框架當然,也是開源的,并且在整個過程中節省了上百萬美元。另一方面,被證實有一些嚴重的缺點部署困難而且慢。在緩存刷新期間,當可用于別的進程的已緩存的文件字節碼在此時損壞,就會導致崩潰。 How Badoo saved one million dollars switching to PHP7 我們成功的把我們的應用遷移到了php7上面(數百臺機...
閱讀 1598·2021-11-04 16:11
閱讀 3309·2021-09-09 11:33
閱讀 1558·2019-08-30 15:54
閱讀 619·2019-08-30 15:44
閱讀 3174·2019-08-30 15:43
閱讀 2554·2019-08-30 13:06
閱讀 1698·2019-08-29 17:00
閱讀 895·2019-08-29 15:33