Zend_Controller_Front->dispatch 注解

本文介绍Zend框架中的调度过程,包括初始化、路由、插件注册、请求与响应对象配置等关键步骤,并详细解释了如何通过Zend_Controller_Front进行调度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Zend_Controller_Front
public   function  dispatch(Zend_Controller_Request_Abstract  $request   =   null ,  Zend_Controller_Response_Abstract  $response   =   null )
{

//     注册出错的插件

    
if  ( ! $this -> getParam( ' noErrorHandler ' &&   ! $this -> _plugins -> hasPlugin( ' Zend_Controller_Plugin_ErrorHandler ' )) {
        
//  Register with stack index of 100 该插件存放在序号是 100的位置
         $this -> _plugins -> registerPlugin( new  Zend_Controller_Plugin_ErrorHandler() ,   100 );
    }

//     添加视图渲染助手
     if  ( ! $this -> getParam( ' noViewRenderer ' &&   ! Zend_Controller_Action_HelperBroker :: hasHelper( ' viewRenderer ' )) {
        Zend_Controller_Action_HelperBroker
:: addHelper( new  Zend_Controller_Action_Helper_ViewRenderer());
    }

// 设置请求对象 如果没提供则实例化默认http方式的请求对象(该对象封装了 module  controller  action 对应的名字 及对$_GET  $_POST )
     /* *
     * Instantiate default request object (HTTP version) if none provided
     
*/
    
if  ( null   !==   $request ) {
        
$this -> setRequest( $request );
    } 
elseif  (( null   ===   $request &&  ( null   ===  ( $request   =   $this -> getRequest()))) {
        
require_once   ' Zend/Controller/Request/Http.php ' ;
        
$request   =   new  Zend_Controller_Request_Http();
        
$this -> setRequest( $request );
    }

// 重新设置 BaseUrl  通过调用 request对象的 setBaseUrl
         /* *
         * Set base URL of request object, if available
         
*/
        
if  ( is_callable ( array ( $this -> _request ,   ' setBaseUrl ' ))) {
            
if  ( null   !==  ( $baseUrl   =   $this -> getBaseUrl())) {     // 存在 $baseUrl 时才执行
                 $this -> _request -> setBaseUrl( $baseUrl );
            }
        }

// 设置 响应对象 如果没提供则实例化默认http方式的响应对象 (该对象处理服务端向客户端的响应 比如 显示网页内容)
         /* *
         * Instantiate default response object (HTTP version) if none provided
         
*/
        
if  ( null   !==   $response ) {
            
$this -> setResponse( $response );
        } 
elseif  (( null   ===   $this -> _response)  &&  ( null   ===  ( $this -> _response  =   $this -> getResponse()))) {
            
require_once   ' Zend/Controller/Response/Http.php ' ;
            
$response   =   new  Zend_Controller_Response_Http();
            
$this -> setResponse( $response );
        }

// 把 request 和 response 对象保存在 提供的plugin 中
         /* *
         * Register request and response objects with plugin broker
         
*/
        
$this -> _plugins
             
-> setRequest( $this -> _request)
             
-> setResponse( $this -> _response);


// 初始化路由
         /* *
         * Initialize router
         
*/
        
$router   =   $this -> getRouter();     // 这里是采用 Zend_Controller_Router_Rewrite 
         $router -> setParams( $this -> getParams());     // 传递引用的参数到路由

//初始化调配器

         /* *
         * Initialize dispatcher
         
*/
        
$dispatcher   =   $this -> getDispatcher();         // 这里是采用 Zend_Controller_Dispatcher_Standard
         $dispatcher -> setParams( $this -> getParams())
                   
-> setResponse( $this -> _response);     // 保存 Response 在 dispatcher 因为在 Zend_Controller_Action 中用到

    //开始 调配过程
       // Begin dispatch

         try  {
            
/* *
             * Route request to controller/action, if a router is provided
             
*/

            
/* *
            * Notify plugins of router startup        通知各个插件 路由启动
            
*/
            
$this -> _plugins -> routeStartup( $this -> _request);

            
$router -> route( $this -> _request);         // 启动路由 得到了 module  controller  action 值

            
/* *
            * Notify plugins of router completion    通知各个插件 路由结束
            
*/
            
$this -> _plugins -> routeShutdown( $this -> _request);

            
/* *
             * Notify plugins of dispatch loop startup        通知各个插件 调配 循环开始
             
*/
            
$this -> _plugins -> dispatchLoopStartup( $this -> _request);

           
/* *
             *  Attempt to dispatch the controller/action. If the $this->_request
             *  indicates that it needs to be dispatched, move to the next
             *  action in the request.
             
*/
         
// 根据当前的 controller/action 尝试进行调配  对于Request 指定 dispatched 的请求 跳过 
             do  {
                
$this -> _request -> setDispatched( true );

                
/* *
                 * Notify plugins of dispatch startup     通知插件 开始调配
                 
*/
                
$this -> _plugins -> preDispatch( $this -> _request);

                
/* *
                 * Skip requested action if preDispatch() has reset it 对于Request 指定 dispatched 的请求 跳过 
                 
*/
                
if  ( ! $this -> _request -> isDispatched()) {
                    
continue ;
                }

                
/* *
                 * Dispatch request    调用 Zend_Controller_Dispatcher_Standard-dispatch()
                 
*/
                
try  {
                    
$dispatcher -> dispatch( $this -> _request ,   $this -> _response);
                } 
catch  ( Exception   $e ) {
                    
if  ( $this -> throwExceptions()) {
                        
throw   $e ;
                    }
                    
$this -> _response -> setException( $e );
                }
                
/* *
                 * Notify plugins of dispatch completion    调用 Zend_Controller_Plugin_Broker->postDispatch 通知所有插件完成当前调配
                 
*/
                
$this -> _plugins -> postDispatch( $this -> _request);
            } 
while  ( ! $this -> _request -> isDispatched());
        } 
catch  ( Exception   $e ) {
            
if  ( $this -> throwExceptions()) {
                
throw   $e ;
            }

            
$this -> _response -> setException( $e );
        }


        
/* *
         * Notify plugins of dispatch loop completion 通知所有插件完成所有调配
         
*/
        
try  {
            
$this -> _plugins -> dispatchLoopShutdown();
        } 
catch  ( Exception   $e ) {
            
if  ( $this -> throwExceptions()) {
                
throw   $e ;
            }

            
$this -> _response -> setException( $e );
        }

        
if  ( $this -> returnResponse()) {     // 如果设制了 返回响应
             return   $this -> _response;
        }

        
$this -> _response -> sendResponse();     // 发送响应到客户端

}
 
bool lv_draw_dispatch_layer(lv_display_t * disp, lv_layer_t * layer) { LV_PROFILER_BEGIN; /*Remove the finished tasks first*/ lv_draw_task_t * t_prev = NULL; lv_draw_task_t * t = layer->draw_task_head; while(t) { lv_draw_task_t * t_next = t->next; if(t->state == LV_DRAW_TASK_STATE_READY) { if(t_prev) t_prev->next = t->next; /*Remove it by assigning the next task to the previous*/ else layer->draw_task_head = t_next; /*If it was the head, set the next as head*/ /*If it was layer drawing free the layer too*/ if(t->type == LV_DRAW_TASK_TYPE_LAYER) { lv_draw_image_dsc_t * draw_image_dsc = t->draw_dsc; lv_layer_t * layer_drawn = (lv_layer_t *)draw_image_dsc->src; if(layer_drawn->draw_buf) { int32_t h = lv_area_get_height(&layer_drawn->buf_area); uint32_t layer_size_byte = h * layer_drawn->draw_buf->header.stride; _draw_info.used_memory_for_layers_kb -= get_layer_size_kb(layer_size_byte); LV_LOG_INFO("Layer memory used: %" LV_PRIu32 " kB\n", _draw_info.used_memory_for_layers_kb); lv_draw_buf_destroy(layer_drawn->draw_buf); layer_drawn->draw_buf = NULL; } /*Remove the layer from the display's*/ if(disp) { lv_layer_t * l2 = disp->layer_head; while(l2) { if(l2->next == layer_drawn) { l2->next = layer_drawn->next; break; } l2 = l2->next; } if(disp->layer_deinit) disp->layer_deinit(disp, layer_drawn); lv_free(layer_drawn); } } lv_draw_label_dsc_t * draw_label_dsc = lv_draw_task_get_label_dsc(t); if(draw_label_dsc && draw_label_dsc->text_local) { lv_free((void *)draw_label_dsc->text); draw_label_dsc->text = NULL; } lv_free(t->draw_dsc); lv_free(t); } else { t_prev = t; } t = t_next; } bool task_dispatched = false; /*This layer is ready, enable blending its buffer*/ if(layer->parent && layer->all_tasks_added && layer->draw_task_head == NULL) { /*Find a draw task with TYPE_LAYER in the layer where the src is this layer*/ lv_draw_task_t * t_src = layer->parent->draw_task_head; while(t_src) { if(t_src->type == LV_DRAW_TASK_TYPE_LAYER && t_src->state == LV_DRAW_TASK_STATE_WAITING) { lv_draw_image_dsc_t * draw_dsc = t_src->draw_dsc; if(draw_dsc->src == layer) { t_src->state = LV_DRAW_TASK_STATE_QUEUED; lv_draw_dispatch_request(); break; } } t_src = t_src->next; } } /*Assign draw tasks to the draw_units*/ else { /*Find a draw unit which is not busy and can take at least one task*/ /*Let all draw units to pick draw tasks*/ lv_draw_unit_t * u = _draw_info.unit_head; while(u) { int32_t taken_cnt = u->dispatch_cb(u, layer); if(taken_cnt != LV_DRAW_UNIT_IDLE) task_dispatched = true; u = u->next; } } LV_PROFILER_END; return task_dispatched; }
最新发布
03-23
<think>好的,我现在需要分析用户提供的函数`bool lv_draw_dispatch_layer(lv_display_t * disp, lv_layer_t * layer)`,并解释它的功能。让我先仔细阅读代码,理解各个部分的作用。 首先,函数开始和结束处有性能分析的宏`LV_PROFILER_BEGIN`和`LV_PROFILER_END`,说明这个函数可能是性能关键部分,需要监控执行时间。 接下来看第一部分,处理已完成的任务。代码遍历`layer->draw_task_head`链表,检查每个任务的状态是否为`LV_DRAW_TASK_STATE_READY`。如果是,就移除该任务,并处理相关资源。特别是当任务类型是`LV_DRAW_TASK_TYPE_LAYER`时,需要释放对应的图层资源,比如`draw_buf`,并从显示器的图层链表中移除该图层。这可能涉及到内存管理和资源释放,需要注意指针操作是否正确,比如链表的断开和内存的释放。 然后处理标签描述符,如果`text_local`存在,需要释放文本内容的内存。这部分需要确保释放的是正确的指针,避免内存泄漏或重复释放。 接下来是第二部分,处理任务分发。如果当前图层已经准备就绪,并且所有任务都添加完成且没有剩余任务,则查找父图层中的对应任务,将其状态设为`LV_DRAW_TASK_STATE_QUEUED`,并请求分发。这可能是为了图层合成,确保父图层能正确使用子图层的内容。 否则,遍历所有的绘制单元(`draw_unit`),调用它们的`dispatch_cb`回调函数,分发任务。如果任何一个单元处理了任务,就将`task_dispatched`设为true,最终返回这个状态。 在这个过程中,需要注意链表操作的准确性,尤其是在删除节点时如何处理前驱和后继节点,避免出现悬空指针或内存泄漏。同时,资源释放部分需要检查是否正确释放了图层相关的缓冲区和描述符,特别是在处理`LV_DRAW_TASK_TYPE_LAYER`类型任务时。 可能的问题点包括:链表遍历时是否正确处理了节点的删除,尤其是在头节点被删除的情况下;释放内存后是否将指针置为NULL,避免野指针;在多图层情况下,是否正确更新了显示器的图层链表;以及各个回调函数是否正确调用,比如`layer_deinit`和`dispatch_cb`。 此外,函数返回的`task_dispatched`变量用于指示是否有任务被分发,这可能会影响后续的绘制流程,比如是否需要继续处理或等待。 总结一下,这个函数主要负责管理绘图任务的清理和分发,确保资源正确释放,任务有效分配到绘制单元,同时处理图层之间的依赖关系。需要确保每一步操作都正确无误,尤其是在内存管理和链表操作上。</think>以下是对 `bool lv_draw_dispatch_layer(lv_display_t * disp, lv_layer_t * layer)` 函数的逐步分析: --- ### **功能概述** 该函数是 **LVGL图形库** 中负责图层绘制任务调度与资源管理的核心函数。主要完成以下操作: 1. **清理已完成的任务**:释放已完成的绘制任务及关联资源。 2. **图层合成处理**:管理子图层的缓冲区与父图层的绘制任务状态。 3. **任务分发**:将未完成的任务分配给绘图单元执行。 --- ### **详细步骤解析** #### **1. 清理已完成任务** ```c lv_draw_task_t * t_prev = NULL; lv_draw_task_t * t = layer->draw_task_head; while(t) { // 遍历任务链表,移除状态为 READY 的任务 if(t->state == LV_DRAW_TASK_STATE_READY) { // 从链表中移除任务节点 if(t_prev) t_prev->next = t->next; else layer->draw_task_head = t_next; // 特殊处理图层类型任务 if(t->type == LV_DRAW_TASK_TYPE_LAYER) { // 释放子图层缓冲区内存 lv_draw_buf_destroy(layer_drawn->draw_buf); layer_drawn->draw_buf = NULL; // 从显示器的图层链表中移除子图层 l2->next = layer_drawn->next; // 调用反初始化回调并释放子图层内存 if(disp->layer_deinit) disp->layer_deinit(disp, layer_drawn); lv_free(layer_drawn); } // 释放标签文本内存(如果存在) if(draw_label_dsc && draw_label_dsc->text_local) { lv_free((void *)draw_label_dsc->text); } // 释放任务描述符及任务本身 lv_free(t->draw_dsc); lv_free(t); } // 继续处理下一个任务 t = t_next; } ``` - **关键点**: - 链表操作需正确处理前驱节点 (`t_prev`) 以维护链表完整性。 - 对 `LV_DRAW_TASK_TYPE_LAYER` 类型任务,需递归释放子图层资源并更新内存统计。 --- #### **2. 图层合成处理** ```c if(layer->parent && layer->all_tasks_added && layer->draw_task_head == NULL) { // 查找父图层中等待状态的图层任务 while(t_src) { if(t_src->type == LV_DRAW_TASK_TYPE_LAYER && t_src->state == LV_DRAW_TASK_STATE_WAITING) { // 更新任务状态为已排队,触发合成请求 t_src->state = LV_DRAW_TASK_STATE_QUEUED; lv_draw_dispatch_request(); break; } t_src = t_src->next; } } ``` - **作用**: - 当子图层所有任务完成且无剩余任务时,通知父图层进行合成。 - 通过修改任务状态 (`QUEUED`) 和调用 `lv_draw_dispatch_request()` 触发后续绘制流程。 --- #### **3. 任务分发至绘图单元** ```c lv_draw_unit_t * u = _draw_info.unit_head; while(u) { // 调用绘图单元的分发回调函数 int32_t taken_cnt = u->dispatch_cb(u, layer); if(taken_cnt != LV_DRAW_UNIT_IDLE) task_dispatched = true; u = u->next; } ``` - **逻辑**: - 遍历所有绘图单元(如GPU、CPU渲染器),尝试分配任务。 - 若单元接受任务(返回值非 `LV_DRAW_UNIT_IDLE`),标记任务已分发。 --- ### **返回值** - **`task_dispatched`**: - `true`: 有任务被分发到绘图单元。 - `false`: 所有绘图单元空闲或无任务可处理。 --- ### **技术要点总结** 1. **资源管理**: - 动态内存释放需严格匹配分配方式(如 `lv_free` 对应 `lv_malloc`)。 - 图层缓冲区的销毁需更新全局内存统计 (`_draw_info.used_memory_for_layers_kb`)。 2. **状态机控制**: - 任务状态(`READY`, `WAITING`, `QUEUED`)驱动绘制流程的推进。 3. **链表操作**: - 正确处理头节点删除和中间节点移除,避免内存泄漏或链表断裂。 --- ### **应用场景** 此函数在LVGL的渲染循环中调用,常见于: - 屏幕刷新时处理图层绘制任务。 - 动态UI更新后重新合成图层。 - 资源受限环境下确保内存高效复用。 通过逐层调度和资源回收,保障嵌入式设备上的流畅图形渲染。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值