0

I am not an experinced c++ programmer. So I just want to know how to implement timer and timertask just like java has in C++. I have tried timer_create example that is in man page of timer_create but It is not working as per my requirement. I want that after particualar time span an event should fire, and if specific condition fulfills then timer should be canceled.

Any help would be highly appreciated. Thanks, Yuvi.

Yuvi
  • 1,344
  • 4
  • 24
  • 46
  • I can't speak for c++11, but in the rest of the (standard) c++ lexicon, no. Qt and Boost have some great concurrency tools available, though. – jpm Apr 06 '12 at 10:49

2 Answers2

3

I too was looking for a Java like TimerTask but I needed one for Windows C++ when I came across this question. After a day of researching mostly on SO and learning about passing class member functions, I was able to put together a solution that seems to work well for me. I realize that I am years late in answering this question but maybe someone still looking for this solution will find this useful.

This is a Windows only solution which I tested on Windows 10 using Visual Studio C++. I'm still learning C++ so please be gentle if I've broken any rules. I realize the exceptions are elementary but they are easy to customize to your needs. I created a TimerTask class similar to the Java class. You'll need to derive a new user class from the TimerTask class and create a "task" function that includes the code you want executed at regular intervals. Here is the TimerTask class:

--TimerTask.h--
#pragma once
#include <thread>

class TimerTask {
    HANDLE timeoutEvent;
    DWORD msTimeout;
    bool exit = false;
    void* pObj;

    static void taskWrapper(TimerTask* pObj) {
        while (!pObj->exit) {
            DWORD waitResult = WaitForSingleObject(pObj->timeoutEvent, pObj->msTimeout);
            if (pObj->exit)
                break;
            pObj->task();
        }
    }

public:

    TimerTask::TimerTask() {
        timeoutEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
        if (!timeoutEvent) {
            throw "TimerTask CreateEvent Error: ";
        }
    }

    TimerTask::~TimerTask() {
        CloseHandle(timeoutEvent);
    }

    // Derived class must create task function that runs at every timer interval.
    virtual void task() = 0;

    void start(void* pObj, DWORD msTimeout) {
        this->pObj = pObj;
        this->msTimeout = msTimeout;

        std::thread timerThread(taskWrapper, (TimerTask*)pObj);
        timerThread.detach();
    }

    void stop() {
        exit = true;
        if (!SetEvent(timeoutEvent))
            throw "TimerTask:stop(): Error: ";
    }
};

And here is a sample of usage. For brevity I didn't include error checking.

--Test.cpp--
#include "Windows.h"
#include <iostream>
#include "TimerTask.h"

using namespace std;

class KeepAliveTask : public TimerTask {
public:
    void task() {
        cout << "Insert your code here!\n";
    }
};

int main()
{
    cout << "Hello, TimerTask!\n";

    KeepAliveTask keepAlive;
    keepAlive.start(&keepAlive, 1000);  // Execute once per second

    Sleep(5100);    // Pause 5.1s to give time for task thread to run.
    keepAlive.stop();
    Sleep(1000);    // Pause another sec to give time for thread to stop.

    return 0;
}
Gary G.
  • 318
  • 3
  • 12
  • I want to do it for linux environment. But the windows functions like WaitForSingleObject, CreateEvent and the Handle type aren't exist. I am begginer at c++ and i need this part of code. Can you help me if it's easy for you? – Talha Ç Aug 26 '22 at 09:48
2

This is generally a very difficult question, since you are inherently asking for some concurrent, or at least asynchronous processing.

The simplest, single-threaded solution is to use something like Posix's alarm(2). This will cause a signal to be sent to your process after a specified time. You need to register a signal handler (e.g. with signal(2)), but you are subject to all its limitations (e.g. you must only call async-safe functions within the handler).

A second, single-threaded option is to use a select-style (or epoll-style) I/O loop and use a kernel timer file descriptor. This is a very recent Linux feature, though, so availability will vary.

Finally, the typical, general solution is to use multiple threads: Make a dedicated thread for the timer whose only purpose is to sleep for the set time span and then execute some code. For this you will have to bear the full weight of concurrent programming responsibilities, such as handling shared data, guaranteeing the absence of races, etc.

Some higher-level libraries like Boost.ASIO and the new standard library provide some nice timing mechanisms once you've decided to go down the multithreaded route.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • For now I am using something like your first suggestion, `alaram` , `setitimer`. Now how to enusre that functions are async-safe ? – Yuvi Apr 06 '12 at 11:26
  • @Yuvi: Read the manual. There's a list of async-safe functions. I think `abort` and `exec` are among them. The primary thing you should do in a signal handler is modify a global variable of type `volatile sigatomic_t`, though. – Kerrek SB Apr 06 '12 at 11:28
  • @Yuvi: Specifically, read the `signal(7)` manpage for the full list of safe Posix functions. – Mike Seymour Apr 06 '12 at 12:03
  • @MikeSeymour I have readed signal for section 7. We can say that all function which direclty calls ioctl call are async-safe, correct me if I am wrong. – Yuvi Apr 06 '12 at 12:11
  • @Yuvi: No, `ioctl` is not on the list of guaranteed safe functions. – Mike Seymour Apr 06 '12 at 12:15
  • @KerrekSB What about using `timer_create` ? – Yuvi Apr 10 '12 at 10:02
  • @Yuvi: Yes, sure. That looks like an advanced version of `alarm`. If you use signals, you'll have the same constraints. – Kerrek SB Apr 10 '12 at 14:09