我有一个我设置的计时器类,可以使用std::function
模板绑定到一个自由浮动函数。我想修改类以支持使用自由浮动函数和类成员函数。我知道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;
};
}
任何建议都会很棒。如果我需要澄清任何内容,请告诉我。
由于
答案 0 :(得分:2)
要将成员函数传递给此函数,请将指针传递给未绑定的成员函数(&Engine::SceneManager::Update
),然后第一个参数是指向应该调用该成员的对象的指针(指向{的指针{1}}对象,这是“隐藏的”SceneManager
指针)。这就是 bind 的工作原理,因此您的代码不需要进行任何更改。作为一个简单的替代方案,传递一个lambda。
http://coliru.stacked-crooked.com/a/7c6335d4f94b9f93(虽然没有按预期运行,我不知道为什么)
<小时/> 另外,我很困惑你的代码将interal作为size_t,然后将其转换为纳秒,然后将其转换为微秒,然后使用它。为什么不直接使用微秒?
你的析构函数有竞争条件。禁用应该停止,直到线程执行完毕。我没有多少使用this
,但我猜一个地方是std::thread
作为其中的一部分,让线程一次只能睡100ms可能是有用的,并定期检查是否应该关闭。
if (_thread.is_joinable()) _thread.join();
应该在开始新线程之前停止现有线程。更好的是,重用相同的线程。不幸的是,现有的线程切换任务没有简单的方法,所以最简单的方法就是Enable
,然后保留现有的代码。