• 8. 异步操作


    对于游戏开发而言,经常使用到异步相关操作,因此在使用moduleframework之前应该提供一个异步操作的类。 以后相关的异步操作均继承这个类

    AsyncOperation:

    先贴出代码:

    #ifndef __ASYNC_OPERATION_H__
    #define __ASYNC_OPERATION_H__
    #include <boost/function.hpp>
    
    class AsyncOperation
    {
    public:
        typedef boost::function(void<AsyncOperation*>) TypeOnExecute;
        typedef boost::function(void<AsyncOperation*>) TypeOnComplete;
        typedef boost::function(void<AsyncOperation*>) TypeOnAborted;
    
        // 委托执行函数
        explicit AsyncOperation(TypeOnExecute onExecute)
            :_onExecute(onExecute)
        {
            if(!_onExecute) throw "onExecute is NULL";
        }
    
        virtual AsyncOperation(){}
    
        void Execute(TypeOnComplete onComplete, TypeOnAborted onAorted = NULL)
        {
            if (!_onComplete) throw "onComplete is NULL"
            _onComplete = onComplete;
            _onAborted = onAorted;
            _onExecute(this);
        }
    
        virtual void Abort()
        {
    
        }
    
        void Complete()
        {
            _onComplete(this);
        }
    
    private:
        TypeOnExecute _onExecute;
        TypeOnComplete _onComplete;
        TypeOnAborted _onAborted;
    
    };
    #endif


    真正的执行函数是Execute 另外提供了一个完成 和终止的接口。

    这个类应该比较简单。

    在此类的基础上构建一个异步队列。  AsyncQueue继承该类

    #ifndef __ASYNC_QUEUE_H__
    #define __ASYNC_QUEUE_H__
    
    #include <glog/logging.h>
    #include "AsyncOpertaion.hpp"
    #include <boost/bind.hpp>
    #include <deque>
    
    using namespace std;
    
    class AsyncQueue : public AsyncQueue
    {
    public:
        // 构造函数默认调用ExecuteNextChild来启动整个异步进程
        AsyncQueue(): AsyncOperation(boost::bind(&AsyncQueue::ExecuteNextChild, this, _1))
            , _abortFlag(false)
        {
    
        }
        ~AsyncQueue()
        {
            TypeOptQueue::iterator it = _queue.begin();
            for (; it != _queue.end(); ++it)
            {
                delete *it;
            }
        }
    
        // 加入队列
        void Push(AsyncOperation* operation)
        {
            _queue.push_back(operation);
        }
    
        // 终止执行
        void Abort()
        {
            if(_queue.empty()) return;
            _abortFlag = true;
            AsyncOperation* front = _queue.front();
            front->Abort(); // 终止队列首位的执行
        }
    
    private:
        void ExecuteNextChild(AsyncOperation* operation)
        {
            if(_queue.empty())
            {
                LOG(ERROR) << "Async Queue is Empty!";
                return;
            }
            // 迭代执行_queue中的操作
            AsyncOperation* front = _queue.front();
            front->Execute(boost::bind(&AsyncQueue::OnChildComplete, this, _1));
        }
    
        void OnChildComplete(AsyncOperation* operation)
        {
            // 移除已执行的异步操作
            _queue.pop_front();
            delete operation;
            if (_queue.empty())
            {
                // 通知队列执行完成
                Complete();
                return;
            }
    
            if (_abortFlag && _onAborted)
            {
                _onAborted(this);
            }else
            {
                // 迭代执行
                ExecuteNextChild(0);
            }
        }
    
    private:
        typedef deque<AsyncOperation*> TypeOptQueue; // 使用队列来包装
        TypeOptQueue _queue;
        bool _abortFlag; 
    };
    
    #endif


    这里一个巧妙指出在于 如果迭代执行整个异步队列, 注意看 构造函数和OnExecuteNextChild 这两点 。  


    至此我们构建了一个初步的异步队列。以后其他各个模块均继承他们。 比如模块的初始化等

  • 相关阅读:
    Microsoft Biztalk Server 2000简介
    BizTalk学习笔记系列之二:实例说明如何使用BizTalk
    BizTalk学习笔记系列之三:企业集成应用和BizTalk
    简单状态机Workflow基于Web应用【转】
    C#类、接口、虚方法和抽象方法
    多表查询语句写法、数据库数字如何转化为汉子、Sql语句拼接
    IsPostBack用法
    Net前台页面如何调用后台cs变量
    aspx页面中写if else 语句的方法,
    查询数据库最大的索引、静态类与非静态类的区别、后台操作DIV样式的方法、C#操作TreeView组件中的一些常用方法及具体实现
  • 原文地址:https://www.cnblogs.com/riskyer/p/3323110.html
Copyright © 2020-2023  润新知