<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                # 4.0 協程實現原理 內存棧 ---- `4.0`版本使用了`PHP`+`C`的雙棧模式。創建協程時會創建一個`C`棧,默認尺寸為`2M`,創建一個`PHP`棧,默認為`8K`。 `C`棧主要用于保存底層函數調用的局部變量數據,用于解決`call_user_func`、`array_map`等`C`函數調用在協程切換時未能還原的問題。`4.0`版本無論如何切換協程,底層總是能正確地切換回原先的`C`函數棧幀繼續向下執行。 `4.0`底層還支持了嵌套關系,在協程內創建子協程,子協程掛起時仍然可以恢復父協程的執行。 ```cpp Context::Context(size_t stack_size, coroutine_func_t fn, void* private_data) : fn_(fn), stack_size_(stack_size), private_data_(private_data) { protect_page_ = 0; end = false; swap_ctx_ = NULL; stack_ = (char*) sw_malloc(stack_size_); swDebug("alloc stack: size=%u, ptr=%p.", stack_size_, stack_); } ``` `PHP`棧主要保存`PHP`函數調用的局部變量數據,主要是`zval`結構體,`PHP`中標量類型,如整型、浮點型、布爾型等是直接保存在`zval`結構體內的,而`object`、`string`、`array`是使用引用計數管理,在堆上存儲的。`8K`的`PHP`棧足以保存整個函數調用的局部變量。 ```c static inline void sw_vm_stack_init(void) { uint32_t size = COROG.stack_size; zend_vm_stack page = (zend_vm_stack) emalloc(size); page->top = ZEND_VM_STACK_ELEMENTS(page); page->end = (zval*) ((char*) page + size); page->prev = NULL; EG(vm_stack) = page; EG(vm_stack)->top++; EG(vm_stack_top) = EG(vm_stack)->top; EG(vm_stack_end) = EG(vm_stack)->end; } ``` 協程切換 ---- `C`棧切換使用了`boost.context 1.60`匯編代碼,用于保存寄存器,切換指令序列。主要是`jump_fcontext`這個`ASM`函數提供。`PHP`棧的切換是跟隨`C`棧切同步進行的。底層會切換`EG(vm_stack)`使得`PHP`恢復到正確的`PHP`函數棧幀。`4.0.2`版本還增加了`ob`輸出緩存區的切換,`ob_start`等操作也可以用于協程。 ```c int sw_coro_resume(php_context *sw_current_context, zval *retval, zval *coro_retval) { coro_task *task = SWCC(current_task); resume_php_stack(task); if (EG(current_execute_data)->prev_execute_data->opline->result_type != IS_UNUSED && retval) { ZVAL_COPY(SWCC(current_coro_return_value_ptr), retval); } if (OG(handlers).elements) { php_output_deactivate(); if (!SWCC(current_coro_output_ptr)) { php_output_activate(); } } if (SWCC(current_coro_output_ptr)) { memcpy(SWOG, SWCC(current_coro_output_ptr), sizeof(zend_output_globals)); efree(SWCC(current_coro_output_ptr)); SWCC(current_coro_output_ptr) = NULL; } swTraceLog(SW_TRACE_COROUTINE, "cid=%d", task->cid); coroutine_resume_naked(task->co); if (unlikely(EG(exception))) { if (retval) { zval_ptr_dtor(retval); } zend_exception_error(EG(exception), E_ERROR TSRMLS_CC); } return CORO_END; } ``` 協程調度 ---- `4.0`協程實現中,主協程即為`Reactor`協程,負責整個`EventLoop`的運行。在`Swoole 4`版本中,可以**同時**使用**協程**和**異步回調**兩種編程模式。異步回調的函數執行,將全部在主協程內執行。 除了執行異步回調之外,主協程還負責調度其他工作協程。 #### 協程掛起 在工作協程中執行一些`IO`操作時,底層會將`IO`事件注冊到`EventLoop`,并讓出執行權。 * 嵌套創建的非初代協程,會逐個讓出到父協程,直到回到主協程 * 在主協程上創建的初代協程,會立即回到主協程 * 主協程的`Reactor`會繼續處理`IO`事件、`Wait`監聽新事件(`epoll_wait`) #### 協程恢復 當主協程的`Reactor`接收到新的`IO`事件,會判斷事件類型,執行不同的操作。如果是異步回調,會在主協程內直接執行。如果是屬于某個掛起協程的事件,底層會掛起主協程,并恢復對應的工作協程。該工作協程掛起或退出時,會再次回到主協程。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看