Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++ Implementing Timed Callback function

I want to implement some system in c++ so that I can call a function and ask for another function to be called in X milliseconds. Something like this:

callfunctiontimed(25, funcName);

25 being the amount of milliseconds before the function should be called.

I would like to know if multithreading is required for this and then use some delay function? Other than using function pointer how would a feature like this work?

like image 326
DavidColson Avatar asked Oct 15 '12 21:10

DavidColson


People also ask

What is a timer callback function?

The timer object supports properties that let you specify the MATLAB® commands that execute when a timer fires, and for other timer object events, such as starting, stopping, or when an error occurs. These are called callbacks.

What is callback function in C with example?

A callback is any executable code that is passed as an argument to other code, which is expected to call back (execute) the argument at a given time [Source : Wiki]. In simple language, If a reference of a function is passed to another function as an argument to call it, then it will be called as a Callback function.

Why do we need callback functions in C?

Callback functions are an essential and often critical concept that developers need to create drivers or custom libraries. A callback function is a reference to executable code that is passed as an argument to other code that allows a lower-level software layer to call a function defined in a higher-level layer(10).


2 Answers

For a portable solution, you can use boost::asio. Below is a demo I wrote a while ago. You can change

t.expires_from_now(boost::posix_time::seconds(1));

to suit you need say make function call after 200 milliseonds.

t.expires_from_now(boost::posix_time::milliseconds(200)); 

Below is a complete working example. It's calling repeatedly but I think it should be easy to call only once by just change a bit.

#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
like image 93
RoundPi Avatar answered Sep 21 '22 22:09

RoundPi


Do you want it to by asynchronous so that the callback gets executed when 25 miliseconds are over without blocking the main executing thread? If so, you can execute the callback in a separate thread from the timer / timed callback function you implement.

If you do not use multithreading, then your main or the calling function of callfunctiontimed(25, funcName); would block while you run a sleep / usleep. It is your choice now as to what behavior you want to implement.

The real solution would not be as simple as to multithread or not. There are things like, how do you keep different timers/callbacks information considering the function can be called multiple times with different timeouts and functions.

One way to do it, would be like this:

  1. Create a sorted list of timers/callbacks, sorted based on the time to expire.
  2. Have on main thread and one thread which looks at callbacks/timers, call it timer thread.
  3. When a new callback is added, add it in the sorted list.
  4. The timer thread could be initialized to wait for the least amount of time in the sorted list, or the head. Re-initialize it as new callbacks get added. There would be some math and conditions to take care of.
  5. As the timer thread is done sleeping, it removes and looks at head of the list and executes the function pointer in a new thread. Timer thread is re-initialized with sleep time on the new head of the list.

    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     
        }
    }
    

Hopefully this gives an idea of what I meant, although this is not perfect and has several problems.

like image 41
SeattleOrBayArea Avatar answered Sep 17 '22 22:09

SeattleOrBayArea