简体   繁体   English

std :: function具有计时器C ++的成员函数

[英]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 (尽管它没有按预期运行,我也不知道为什么)


Also, I'm confused by the fact your code takes interal as a size_t, then converts it to nanoseconds, then converts that to microseconds, and then uses it. 另外,我对您的代码将interal作为size_t,然后将其转换为纳秒,然后将其转换为微秒,然后使用它感到困惑。 Why not just use microseconds the whole way through? 为什么不仅仅在整个过程中使用微秒?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM