c ++实现定时回调函数

Dav*_*son 15 c++ function-pointers timing callback

我想在c ++中实现一些系统,这样我就可以调用一个函数并要求在X毫秒内调用另一个函数.像这样的东西:

callfunctiontimed(25, funcName);
Run Code Online (Sandbox Code Playgroud)

25是应该调用函数之前的毫秒数.

我想知道是否需要多线程,然后使用一些延迟功能?除了使用函数指针之外,这样的功能如何工作?

Gob*_*0st 18

对于便携式解决方案,您可以使用boost :: asio.下面是我刚才写的一个演示.你可以改变

t.expires_from_now(boost::posix_time::seconds(1));
Run Code Online (Sandbox Code Playgroud)

适合你需要说200毫米以后的函数调用.

t.expires_from_now(boost::posix_time::milliseconds(200)); 
Run Code Online (Sandbox Code Playgroud)

下面是一个完整的工作示例.它反复调用,但我认为通过改变一点只能调用一次很容易.

#include <iostream>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>

using namespace boost::asio;
using namespace std;

class Deadline 
{
public:
    Deadline(deadline_timer &timer) : t(timer) {
        wait();
    }

    void timeout(const boost::system::error_code &e) {
        if (e)
            return;
        cout << "tick" << endl;
        wait();
    }

    void cancel() {
        t.cancel();
    }


private:
    void wait() {
        t.expires_from_now(boost::posix_time::seconds(1)); //repeat rate here
        t.async_wait(boost::bind(&Deadline::timeout, this, boost::asio::placeholders::error));
    }

    deadline_timer &t;
};


class CancelDeadline {
public:
    CancelDeadline(Deadline &d) :dl(d) { }
    void operator()() {
        string cancel;
        cin >> cancel;
        dl.cancel();
        return;
    }
private:
    Deadline &dl;
};



int main()
{
    io_service io;
    deadline_timer t(io);
    Deadline d(t);
    CancelDeadline cd(d);
    boost::thread thr1(cd);
    io.run();
    return 0;
}



//result:
//it keeps printing tick every second until you enter cancel and enter in the console
tick
tick
tick
Run Code Online (Sandbox Code Playgroud)


Son*_*nny 7

很多人在这里就这个问题提出了很好的答案,但我会直接解决这个问题,因为几年前我遇到过类似的问题.我不能使用Boost有几个原因 - 我知道Boost在许多开源软件中都有很好的用途.此外,我真的很想了解定时器和回调,因为它与基于Linux的环境有关.所以,我写了自己的.

从根本上说,我有一个Timer班级和一个TimerCallback班级.作为类的继承类实现的典型回调TimerCallback将在triggered ()方法中的回调时执行操作,专门针对需求实现.

根据通常的语义,Timer对象与回调对象相关联,回调对象可能包含回调执行所需的所有必需信息.定时器调度由一个环境范围的定时器minheap管理,该定时器必须在单独的线程/进程中维护.这个minheap任务只做了一件事:它最大限度地减少了将来设置的回调事件的最小化.一个minheap选择下一个事件触发的O(1),可以minheapify其余的O(log n)用于n计时器事件.它还可以插入一个新的计时器事件O(log n)(在这里阅读一个温和的堆积介绍).

当计时器触发时,minheap调度程序检查它是否是周期性计时器,单次计时器或将执行特定次数的计时器.因此,定时器对象要么从minheap中移除,要么在下一个执行时间重新插入minheap.如果要删除一个计时器对象,那么它将从minheap中删除(但是计时器对象的删除可能会或可能不会留给创建它的任务)并且堆的其余部分是minheap-ified; 即重新排列以满足minheap属性.

一个工作和单位测试的实现是在这里,并可能包含bug(从我的应用程序中摘录),但我认为它可以帮助别人.实现是基于多进程(fork()ed-process)的(并且还在pthread主任务(进程)中使用s),并使用POSIX共享内存和POSIX消息队列进行进程之间的通信.


Gau*_*nha 6

您是否希望它通过异步进行,以便在25毫秒结束时执行回调而不阻塞主执行线程?如果是这样,您可以在与您实现的定时器/定时回调函数不同的线程中执行回调.

如果你不使用多线程,那么你的main函数或callfunctiontimed的调用函数(25,funcName); 当你跑睡/睡觉时会阻塞.现在您可以选择要实施的行为.

真正的解决方案不会像多线程那样简单.考虑到可以使用不同的超时和功能多次调用该函数,有类似的事情,如何保留不同的计时器/回调信息.

一种方法,就是这样:

  1. 创建一个排序的计时器/回调列表,根据到期时间排序.
  2. 有主线程和一个查看回调/定时器的线程,称之为定时器线程.
  3. 添加新回调后,将其添加到已排序列表中.
  4. 可以初始化计时器线程以等待排序列表或头部中的最少时间.在添加新回调时重新初始化它.会有一些数学和条件需要照顾.
  5. 当计时器线程完成休眠时,它会移除并查看列表的头部并在新线程中执行函数指针.计时器线程在列表的新头上以休眠时间重新初始化.

    main() {
            //spawn a timer thread with pthread create 
    
        callfunctiontimed(25, test); 
        callfunctiontimed(35, show);
        callfunctiontimed(4,  print);
    }
    
    callfunctionTImed(int time, (func*)function, void*data) //
    {
        //add information to sorted list of timer and callbacks
        //re-initialize sleep_time for timer thread if needed. 
        return. 
    }
    timerThread() {
        while(1){
         sleep(sleep_time);
         //look at head of timer list, remove it, call function in a new thread   
         //adjust sleep time as per new head     
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

希望这能说明我的意思,虽然这并不完美,但有几个问题.