[英]std::function With Member Function For Timer C++
I have A timer class that I have set up to be able to bind to a free floating function using the std::function
template. 我有一个计时器类,该类已设置为能够使用std::function
模板绑定到自由浮动函数。 I would Like to modify the class to be able to support using both free floating functions and class member functions. 我想修改类,使其能够使用自由浮动函数和类成员函数来支持。 I know that std::function
can bind to a member function using std::bind
but I am not sure how to set this up with the code I have: 我知道std::function
可以使用std::bind
绑定到成员函数,但是我不确定如何使用我的代码进行设置:
#include <iostream>
#include <chrono>
#include <thread>
#include <functional>
#include <atomic>
namespace Engine {
template<class return_type,class...arguments>
class Timer{
typedef std::function<return_type(arguments...)> _function_t;
public:
Timer(size_t interval,bool autoRun,_function_t function,arguments...args){
_function = function;
_interval = interval;
if (autoRun) {
Enable(args...);
}
}
~Timer(){
if (Running()) {
Disable();
}
}
void Enable(arguments...args){
if (!Running()) {
_running=true;
enable(_interval, _function, args...);
}
}
void Disable(){
if (Running()) {
_running=false;
}
}
std::atomic_bool const& Running()const{
return _running;
}
protected:
void enable(size_t interval,_function_t func,arguments...args){
_thread =std::thread([&,func,interval,args...](){
std::chrono::duration<long long,std::nano> inter(interval);
auto __interval = std::chrono::microseconds(interval);
auto deadline = std::chrono::steady_clock::now();
while (_running) {
func(args...);
std::this_thread::sleep_until(deadline+=__interval);
}
});
_thread.detach();
}
protected:
_function_t _function;
std::atomic_bool _running;
size_t _interval;
std::thread _thread;
};
}
Any suggestions would be great. 任何建议都很好。 Let me know if I need to clarify anything. 让我知道是否需要澄清任何事情。
Thanks 谢谢
To pass a member function to this, pass a pointer to the unbound member function ( &Engine::SceneManager::Update
), and then the first parameter is a pointer to the object who should have the member called (a pointer to a SceneManager
object, this is the "hidden" this
pointer). 要将成员函数传递给此函数,请将指针传递给未绑定的成员函数( &Engine::SceneManager::Update
),然后第一个参数是指向应该调用成员的对象的指针(指向SceneManager
对象的指针,这就是“隐藏” this
指针)。 This is how bind works, so no changes are needed to your code. 绑定就是这样工作的,因此无需更改代码。 As a simple alternative, pass a lambda. 作为一种简单的替代方法,传递一个lambda。
http://coliru.stacked-crooked.com/a/7c6335d4f94b9f93 (though it isn't running as expected and I don't know why) http://coliru.stacked-crooked.com/a/7c6335d4f94b9f93 (尽管它没有按预期运行,我也不知道为什么)
Your destructor has a race condition. 您的析构函数具有竞争条件。 Disable should stall until the thread has finished executing. Disable应该停止,直到线程执行完毕。 I haven't used std::thread
much, but I'd guess one place to start is if (_thread.is_joinable()) _thread.join();
我没有太多使用std::thread
,但是我猜想一个开始的地方是if (_thread.is_joinable()) _thread.join();
As part of this, it might be useful to have the thread only sleep for 100ms at a time or so, and periodically check if it's supposed to be shutting down. 作为此过程的一部分,让线程一次仅睡眠100毫秒左右,并定期检查它是否应该关闭可能是有用的。
Enable
should stop the existing thread, before starting a new one. 在开始新线程之前, Enable
应该停止现有线程。 Better yet, reuse the same thread. 更好的是,重用同一线程。 Unfortunately, there's no easy way to have an existing thread switch tasks, so it's easiest to simply Disable
and then keep your existing code. 不幸的是,没有一个简单的方法来拥有一个现有的线程切换任务,因此最简单的方法就是Disable
并保留现有的代码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.