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()\n" << std::endl; } else{ std::cout << name() <<": cleaning up after SUCCESS\n" << 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() */
标签:std,received,协程,halt,CoroActionNode,Actions,协同程序,action,reply 来源: https://www.cnblogs.com/gary-guo/p/14701129.html