zoukankan      html  css  js  c++  java
  • Async Actions using Coroutines(异步行为使用协程,协同程序)

    Behavior.CPP提供了两个方便使用的抽象去创建一个异步的行为,例如:

    那些行为可能:

    花很长时间来得出结论;

    可能返回RUNNING;

    可能被停止;

    第一类是一个AsyncActionNode,其在单独的线程当中执行方法tick();

    本教程中,引入CoroActionNode,一个不同的行为,其使用coroutines来获得类似的结果;

    主要原因是Coroutines不会生成一个新的线程,更有效率;

    进一步的是,不需要担心你的代码的线程安全;

    在协程中,用户应该现实的调用一个yield(翻译为退出,放弃)方法当用户想让这个行为的执行被挂起的时候;

    CoroActionNode封装了yield方法进一个方便的方法setStatusRunningAndYield().

    下一个例子可以作为你自己实现的一个模板:

    typedef std::chrono::milliseconds Milliseconds;
    
    class MyAsyncAction: public CoroActionNode
    {
      public:
        MyAsyncAction(const std::string& name):
            CoroActionNode(name, {})
        {}
    
      private:
        // This is the ideal skeleton/template of an async action:
        //  - A request to a remote service provider.
        //  - A loop where we check if the reply has been received.
        //  - You may call setStatusRunningAndYield() to "pause".
        //  - Code to execute after the reply.
        //  - A simple way to handle halt().
        NodeStatus tick() override
        {
            std::cout << name() <<": Started. Send Request to server." << std::endl;
    
            TimePoint initial_time = Now();
            TimePoint time_before_reply = initial_time + Milliseconds(100);
    
            int count = 0;
            bool reply_received = false;
    
            while( !reply_received )
            {
                if( count++ == 0)
                {
                    // call this only once
                    std::cout << name() <<": Waiting Reply..." << std::endl;
                }
                // pretend that we received a reply
                if( Now() >= time_before_reply )
                {
                    reply_received = true;
                }
    
                if( !reply_received )
                {
                    // set status to RUNNING and "pause/sleep"
                    // If halt() is called, we will NOT resume execution
                    setStatusRunningAndYield();
                }
            }
    
            // This part of the code is never reached if halt() is invoked,
            // only if reply_received == true;
            std::cout << name() <<": Done. 'Waiting Reply' loop repeated "
                      << count << " times" << std::endl;
            cleanup(false);
            return NodeStatus::SUCCESS;
        }
    
        // you might want to cleanup differently if it was halted or successful
        void cleanup(bool halted)
        {
            if( halted )
            {
                std::cout << name() <<": cleaning up after an halt()
    " << std::endl;
            }
            else{
                std::cout << name() <<": cleaning up after SUCCESS
    " << std::endl;
            }
        }
    
        void halt() override
        {
            std::cout << name() <<": Halted." << std::endl;
            cleanup(true);
            // Do not forget to call this at the end.
            CoroActionNode::halt();
        }
    
        Timepoint Now()
        { 
            return std::chrono::high_resolution_clock::now(); 
        };
    };

    从上面代码可以看出,行为是假设等待了一个请求消息,在100ms之后请求会到达;

    创建一个有两个行为的序列,但是整个序列会在150ms之后被停止;

     <root >
         <BehaviorTree>
            <Timeout msec="150">
                <SequenceStar name="sequence">
                    <MyAsyncAction name="action_A"/>
                    <MyAsyncAction name="action_B"/>
                </SequenceStar>
            </Timeout>
         </BehaviorTree>
     </root>
    int main()
    {
        // Simple tree: a sequence of two asycnhronous actions,
        // but the second will be halted because of the timeout.
    
        BehaviorTreeFactory factory;
        factory.registerNodeType<MyAsyncAction>("MyAsyncAction");
    
        auto tree = factory.createTreeFromText(xml_text);
    
        //---------------------------------------
        // keep executin tick until it returns etiher SUCCESS or FAILURE
        while( tree.tickRoot() == NodeStatus::RUNNING)
        {
            std::this_thread::sleep_for( Milliseconds(10) );
        }
        return 0;
    }
    
    /* Expected output:
    
    action_A: Started. Send Request to server.
    action_A: Waiting Reply...
    action_A: Done. 'Waiting Reply' loop repeated 11 times
    action_A: cleaning up after SUCCESS
    
    action_B: Started. Send Request to server.
    action_B: Waiting Reply...
    action_B: Halted.
    action_B: cleaning up after an halt()
    
    */
  • 相关阅读:
    html5全局属性
    net包之Lookup
    net包之dial拨号和listen监听
    net包之IPConn
    利用 RequireJS 进行依赖项管理
    canvas 学习资料
    net包之UDPConn
    LABjs、RequireJS、SeaJS 哪个最好用?为什么?
    WIA
    Mac OS 10.x.x安装在Vmware虚拟机上!
  • 原文地址:https://www.cnblogs.com/gary-guo/p/14701129.html
Copyright © 2011-2022 走看看