C&C++   发布时间:2022-04-03  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了c – 使用shared_ptr和weak_ptr来管理std :: function safe的生命周期吗?大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
我已经创建了一个包含boost :: asio :: io_service的包装器来处理OpenGL应用程序的GUI线程上的异步任务.

任务可能是从其他线程创建的,因此boost :: asio似乎是这个目的的理想选择,这意味着我不需要编写自己的任务队列以及相关的互斥锁和锁定.我希望在每个帧上完成的工作低于可接受的阈值(例如5ms),因此我调用poll_one直到超出所需的预算,而不是调用run.据我所知,这要求我在发布新任务时调用重置,这似乎运作良好.

因为它很短,所以这就是整个事情,没有#include:

@H_944_11@typedef std::function<void(void)> VoidFunc; typedef std::shared_ptr<class UiTaskQueue> UiTaskQueueRef; class UiTaskQueue { public: static UiTaskQueueRef create() { return UiTaskQueueRef( new UiTaskQueue() ); } ~UiTaskQueue() {} // normally just hand off the results of std/boost::bind to this function: void pushTask( VoidFunc f ) { mservice.post( f ); mservice.reset(); } // called from UI thread; defaults to ~5ms budget (but always does one call) void update( const float &budgetSeconds = 0.005f ) { // getElapsedSeconds is a utility function from the GUI lib I'm using const float t = getElapsedSeconds(); while ( mservice.poll_one() && getElapsedSeconds() - t < budgetSeconds ); } private: UiTaskQueue() {} boost::asio::io_service mservice; };

我在我的主应用程序类中保留了一个UiTaskQueueRef实例,并从我的应用程序的动画循环中@L_364_1@mUiTaskQueue-> update().

我想扩展这个类的功能,以允许任务被取消.我之前的实现(使用几乎相同的接口)为每个任务返回了一个数字ID,并允许使用此ID取消任务.但现在队列和相关锁定的管理由boost :: asio处理我不知道如何最好地做到这一点.

我尝试将任何我想要取消的任务包装在shared_ptr中,并创建一个包装器对象,将weak_ptr存储到任务中并实现()运算符,以便将其传递给io_service.它看起来像这样

@H_944_11@struct CancelableTask { CancelableTask( std::weak_ptr<VoidFunc> f ): mFunc(f) {} void operator()(void) const { std::shared_ptr<VoidFunc> f = mFunc.lock(); if (f) { (*f)(); } } std::weak_ptr<VoidFunc> mFunc; };

然后我的pushTask方法的重载看起来像这样

@H_944_11@void pushTask( std::weak_ptr<VoidFunc> f ) { mservice.post( CancelableTask(f) ); mservice.reset(); }

然后我使用以下方法将可取消的任务发布到队列:

@H_944_11@std::function<void(void)> *task = new std::function<void(void)>( boost::bind(&MyApp::doUiTask,this) ); mTask = std::shared_ptr< std::function<void(void)> >( task ); mUiTaskQueue->pushTask( std::weak_ptr< std::function<void(void)> >( mTask ) );

或者如果您愿意,可以使用VoidFunc typedef:

@H_944_11@VoidFunc *task = new VoidFunc( std::bind(&MyApp::doUiTask,this) ); mTask = std::shared_ptr<VoidFunc>( task ); mUiTaskQueue->pushTask( std::weak_ptr<VoidFunc>( mTask ) );

只要我将shared_ptr保持在mTask周围,io_service就会执行任务.如果我在mTask上调用reset,则weak_ptr无法锁定,并且会根据需要跳过任务.

我的问题实际上是对所有这些新工具的信心:是新的std :: function< void(void)>(std :: bind(…))一件好事,一件安全的事情要管理用shared_ptr?

解决方法

是的,这是安全的.

对于代码

@H_944_11@VoidFunc *task = new VoidFunc( std::bind(&MyApp::doUiTask,this) ); mTask = std::shared_ptr<VoidFunc>( task );

做就是了:

@H_944_11@mTask.reset(new VoidFunc( std::bind(&MyApp::doUiTask,this) ) );

(和其他地方).

请记住,您需要处理竞争条件,即在重置shared_ptr以保持回调活动之前,可能会在weak_ptr上获取锁定,因此即使您关闭代码,您也会偶尔看到回调path重置回调shared_ptr.

大佬总结

以上是大佬教程为你收集整理的c – 使用shared_ptr和weak_ptr来管理std :: function safe的生命周期吗?全部内容,希望文章能够帮你解决c – 使用shared_ptr和weak_ptr来管理std :: function safe的生命周期吗?所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。