Windows timer

Hello everyone!

I need to implement a multi platform timer.

I implemented it on Linux using 'timer_create' and 'timer_settime' calls, but I do not know which similar API calls Windows offers.

Do you know any Windows calls equivalent to Linux calls 'timer_create' and 'timer_settime'?


Thanks a lot!
Last edited on
Hi Thomas thank you very much for your help! I will take a look.

It gets hard some times to find help on Windows platform (much easier on linux ;) )
Codeproject has articles about the WIN API though many of them are for GUIs or MFC.
https://www.codeproject.com/KB/winsdk/
Hi Thomas!

The problem with this approach is that the call 'GetMessage' blocks the application. If you take a look at the example of 'timer_create' here:
'http://man7.org/linux/man-pages/man2/timer_create.2.html'

You will see that the main application has to sleep for a while (simulating a long time task), and then gets interrupted by a signal that is connected with the timer.

I need the same in Windows platform. Maybe I need a combination of Windows signals with timers...
Last edited on
Somehow I don't understand the problem.
If you call the long time task as a function main will wait for it to finish and then continue with other tasks.
Hi Thomas, sorry my English is very bad.

This is an example of a Linux code of what I want:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>

#define INTERRUPT_TIME 3000000000 //Time(in nanoseconds) after which the main application will be interrupted

#define CLOCKID CLOCK_REALTIME
#define SIG SIGRTMIN

#define errExit(msg)    do { perror(msg); exit(EXIT_FAILURE); \
                               } while (0)

static void
handler(int sig, siginfo_t *si, void *uc)
{
    (void) si;
    (void) uc;
    printf("Caught signal %d\n", sig);
    signal(sig, SIG_IGN);
}

int
main(int argc, char *argv[])
{
    timer_t timerid;
    struct sigevent sev;
    struct itimerspec its;
    long long freq_nanosecs;

    struct sigaction sa;


    /* Establish handler for timer signal */
    printf("Establishing handler for signal %d\n", SIG);
    sa.sa_flags = SA_SIGINFO;
    sa.sa_sigaction = handler;
    sigemptyset(&sa.sa_mask);
    if (sigaction(SIG, &sa, NULL) == -1)
        errExit("sigaction");

    /* Create the timer */

    sev.sigev_notify = SIGEV_SIGNAL;
    sev.sigev_signo = SIG;
    sev.sigev_value.sival_ptr = &timerid;
    if (timer_create(CLOCKID, &sev, &timerid) == -1)
        errExit("timer_create");

    /* Start the timer */
    freq_nanosecs = (INTERRUPT_TIME);
    its.it_value.tv_sec = freq_nanosecs / 1000000000;
    its.it_value.tv_nsec = freq_nanosecs % 1000000000;
    its.it_interval.tv_sec = 0;
    its.it_interval.tv_nsec = 0;

    if (timer_settime(timerid, 0, &its, NULL) == -1)
        errExit("timer_settime");

    printf("Sleeping for 50 seconds\n");
    sleep(50); //a long running time task

    exit(EXIT_SUCCESS);
}


You do not need to read the whole program. The long time task would be 'sleep(50);' which sleeps for 50 seconds. However, after 3 seconds the program gets interrupted and executes the callback 'handler'. If I call 'GetMessage', this call would block my application.
Last edited on
Hi Thomas! The call 'SetWaitableTimer' is what I was looking for!! This is an example:
https://docs.microsoft.com/en-us/windows/desktop/sync/using-a-waitable-timer-with-an-asynchronous-procedure-call

However, I only need one more thing... How can I configure the Timer so that it only triggers one time??

I am reading through the documentation but it seems quite hard
I am sorry, I just realized I just need to pass 0 to the third parameter of 'SetWaitableTimer' so it is called only once.
Hi again and sorry for the spam.

It seems I have another problem. In this example 'https://docs.microsoft.com/en-us/windows/desktop/sync/using-a-waitable-timer-with-an-asynchronous-procedure-call', it seems you have to call 'SleepEx' for the timer to be called... If you replace 'SleepEx' with 'std::this_thread::sleep_for' (or my long running task), the callback is not called. I need the callback timer to be executed while executing another long running task. How can I do that?

Thanks!
Is there a reason why you can't use SleepEx?
I am not sure if a timer is actually the best solution.
What does this long running task do?
Report progress, error, finished....

BTW. What's your native language ?
The long running task is waiting for notifications in a condition variable. This is an example code that represents what my application has to do :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include <windows.h>
#include <iostream>
#include <chrono>
#include <thread>
#include <condition_variable>
#include <queue>
#include <atomic>
#include <mutex>

#define TIME_OUT 8000 //8 seconds

static std::queue<int> notifications;
static std::atomic<bool> stopSignal = false;
static std::mutex mutexNotifications;
static MSG Msg;
static std::condition_variable cv;
static bool gotMessage = false;
static bool messageFlag = false;

VOID CALLBACK TimerProc(HWND hWnd, UINT nMsg, UINT nIDEvent, DWORD dwTime)
{
    (void)hWnd;
    (void)nMsg;
    std::cout << "Time: " << dwTime << '\n';
    std::cout.flush();
}

static void run()
{
    UINT TimerId = 0;   
    while (stopSignal.load() == false)
    {
        std::unique_lock<std::mutex> lock(mutexNotifications);
        cv.wait(lock, []
        {
            if (messageFlag)
            {
                return (!notifications.empty() || stopSignal.load() == true || (gotMessage = GetMessage(&Msg, NULL, 0, 0)));
            }
            else
            {
                return (!notifications.empty() || stopSignal.load() == true);
            }
        });

        if (gotMessage)
        {
            DispatchMessage(&Msg);
            gotMessage = false;
            messageFlag = false;
            KillTimer(NULL, TimerId);
        }

        if (!notifications.empty())
        {
            int notification = notifications.front();
            notifications.pop();
            if (notification == 1)//start timer
            {
                messageFlag = true;
                std::cout << "Start timer" << std::endl;
                TimerId = SetTimer(NULL, 0, TIME_OUT, (TIMERPROC)&TimerProc);
            }
            else
            {
                std::cout << "Got " << notification << std::endl;
            }
        }
    }
}

int main(int argc, char *argv[], char *envp[])
{
    std::thread runThread(run);
    int input;

    std::cout << "Start typing integers. 1 to start the timer and 0 to finish." << std::endl;
    while (stopSignal.load() == false)
    {
        std::cin >> input;
        mutexNotifications.lock();
        if (input == 0)
        {
            stopSignal.exchange(true);
        }
        else
        {
            notifications.push(input);
        }
        cv.notify_one();
        mutexNotifications.unlock();
    }

    runThread.join();
    return 0;
}


You only need to execute this code. The application just reads integers (greater than 1) from stdin and shows them in stdout.

However, if you type 1, a timer is started with a delay of 8 seconds. During those 8 seconds, you cannot input any more values because the condition variable predicate is blocked in 'GetMessage'. So my problem is that the application stops processing notifications for 8 seconds.

My native language is Spanish. I know there are many C++ forums in Spanish, but I like this one. People here are always very kind and helpful (like you). Besides I am trying to improve my English as much as I can ;)


Last edited on
Pure C++

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include <iostream>
#include <chrono>
#include <thread>
#include <condition_variable>
#include <queue>
#include <atomic>
#include <mutex>
#include <ctime>

constexpr std::chrono::seconds TIME_OUT(8) ; //8 seconds

static std::queue<int> notifications;
static std::atomic<bool> stopSignal = false;
static std::atomic<bool> time_out = false;
static std::mutex mutexNotifications;
static std::condition_variable cv;

std::string now()
{
    std::time_t t = std::time(nullptr) ;
    return std::asctime( std::localtime( std::addressof(t) ) ) ;
}

static void start_timer()
{
    std::cout << "Start timer at " << now() << std::endl;

    time_out = false ;
    std::this_thread::sleep_for(TIME_OUT) ;
    time_out = true ;
    cv.notify_one();
}

static void run()
{
    while( !stopSignal )
    {
        std::unique_lock<std::mutex> lock(mutexNotifications);
        cv.wait(lock, []
        {
                return( !notifications.empty() || stopSignal || time_out );
        });

        if(time_out)
        {
            std::cout << "time_out at " << now() << std::endl;
            time_out = false ;
        }

        if( !notifications.empty() )
        {
            int notification = notifications.front();
            notifications.pop();
            if (notification == 1) std::thread(start_timer).detach() ; //start timer

            else std::cout << "Got " << notification << std::endl;
        }
    }
}

int main()
{
    std::thread runThread(run);
    int input;

    std::cout << "Start typing integers. 1 to start the timer and 0 to finish." << std::endl;
    while( !stopSignal )
    {
        std::cin >> input;

        std::lock_guard<std::mutex> lock(mutexNotifications);

        if (input == 0) stopSignal = true ;
        else notifications.push(input);

        cv.notify_one();
    }

    runThread.join();
}
Hi JLBorges!

Thank you very much for your answer! The timer callback and the main thread should run in the same thread. I am looking for the same behavior of 'time_create' in Linux. Take a look a this example :

http://man7.org/linux/man-pages/man2/timer_create.2.html#EXAMPLE

As you can see, the main program is interrupted to execute the timer callback. All this happen in the same thread.

Thanks!
I think now I understand what you want.
PeekMessage might be the solution, it checks only if there is a message but doesn't wait for one.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include <windows.h>
#include <iostream>
#include <chrono>
#include <thread>
#include <condition_variable>
#include <queue>
#include <atomic>
#include <mutex>

#define TIME_OUT 8000 //8 seconds

static std::queue<int> notifications;
static std::atomic<bool> stopSignal = false;
static std::mutex mutexNotifications;
static MSG Msg;
static std::condition_variable cv;
static bool gotMessage = false;
static bool messageFlag = false;

VOID CALLBACK TimerProc(HWND hWnd, UINT nMsg, UINT nIDEvent, DWORD dwTime)
{
  UNREFERENCED_PARAMETER(nIDEvent);
  UNREFERENCED_PARAMETER(hWnd);
  UNREFERENCED_PARAMETER(nMsg);

  std::cout << "Time: " << dwTime << '\n';
  std::cout.flush();
}

static void run()
{
  UINT TimerId = 0;
  while (stopSignal.load() == false)
  {
    std::unique_lock<std::mutex> lock(mutexNotifications);
    cv.wait(lock, []
    {
      if (messageFlag)
      {
        return (!notifications.empty() || stopSignal.load() == true || (gotMessage = PeekMessage(&Msg, NULL, 0, 0, PM_NOREMOVE
        )));
      }
      else
      {
        return (!notifications.empty() || stopSignal.load() == true);
      }
    });

    if (gotMessage)
    {
      DispatchMessage(&Msg);
      gotMessage = false;
      messageFlag = false;
      KillTimer(NULL, TimerId);
    }

    if (!notifications.empty())
    {
      int notification = notifications.front();
      notifications.pop();
      if (notification == 1)//start timer
      {
        messageFlag = true;
        std::cout << "Start timer" << std::endl;
        TimerId = SetTimer(NULL, 0, TIME_OUT, (TIMERPROC)&TimerProc);
      }
      else
      {
        std::cout << "Got " << notification << std::endl;
      }
    }
  }
}

int main()
{
  std::thread runThread(run);
  int input;

  std::cout << "Start typing integers. 1 to start the timer and 0 to finish." << std::endl;
  while (stopSignal.load() == false)
  {
    std::cin >> input;
    mutexNotifications.lock();
    if (input == 0)
    {
      stopSignal.exchange(true);
    }
    else
    {
      notifications.push(input);
    }
    cv.notify_one();
    mutexNotifications.unlock();
  }

  runThread.join();
  return 0;
}

Hi Thomas!

I read the PeekMessage documentation and it seems what I was looking for.

However, if I execute your code and type 1, the timer is not triggered... I will take a deeper look at this.

Thank you very much again!
I got a workaround using standard c++. My application has to process two kinds of notifications:

1. Immediate notifications (Notifications to be processed immediately).
2. Delayed notifications.

This is an example code :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#include <iostream>
#include <atomic>
#include <thread>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <chrono>
#define DELAYED_TIME 10000 //MILLISECONDS

class Notification
{
public:

    Notification(std::queue<Notification*>* notificationsQueue)
    : notificationsQueue_(notificationsQueue)
    , isDelayed_(false)
    {
    }

    /**
     * @param delayMillisecons The delay in milliseconds. 0 if the notification is to be processed with no delay.
     */
    void start(size_t delayMillisecons)
    {
        if (delayMillisecons > 0)
        {
            isDelayed_ = true;
        }
        initialTime_ = std::chrono::duration_cast< std::chrono::milliseconds >(std::chrono::system_clock::now().time_since_epoch()).count() + delayMillisecons;
    }

    bool process()
    {
        size_t currentTime = std::chrono::duration_cast< std::chrono::milliseconds >(std::chrono::system_clock::now().time_since_epoch()).count();
        if (currentTime >= initialTime_)
        {
            isDelayed_ ? std::cout << "Processed delayed event" << std::endl : std::cout << "Processed event" << std::endl;
            ;
            return true;
        }
        else
        {
            notificationsQueue_->push(this);
            return false;
        }
    }
private:
    std::queue<Notification*>* notificationsQueue_;
    size_t initialTime_;
    bool isDelayed_;
};

static std::atomic<bool> endSignal;
static std::queue<Notification*> notificationsQueue;
static std::mutex mutexNotifications;
static std::condition_variable condNotification;

static void run()
{
    //let's process notifications
    while (endSignal.load() == false)
    {
        std::unique_lock<std::mutex> lock(mutexNotifications);
        condNotification.wait(lock, []
        {
            return notificationsQueue.empty() == false || endSignal.load() == true;
        });

        if (endSignal.load() == false)
        {
            Notification* notification = notificationsQueue.front();
            notificationsQueue.pop();
            if (notification->process())
            {
                delete notification;
            }
        }
    }
}

int main()
{
    endSignal = false;
    std::thread runThread(run);
    int input;
    Notification* notification = nullptr;
    printf("\n0 to quit.\n");
    printf("1 to push an immediate notification.\n");
    printf("2 to push a delayed notification(10 seconds).\n\n");
    while (endSignal.load() == false)
    {
        std::cin >> input;
        mutexNotifications.lock();
        switch (input)
        {
            case 0:
                endSignal.exchange(true);
                break;
            case 1:
                notification = new Notification(&notificationsQueue);
                notification->start(0);
                notificationsQueue.push(notification);
                break;
            case 2:
                notification = new Notification(&notificationsQueue);
                notification->start(DELAYED_TIME);
                notificationsQueue.push(notification);
                break;
            default:
                std::cerr << "Invalid option" << std::endl;
        }

        condNotification.notify_all();
        mutexNotifications.unlock();
    }

    runThread.join();
}


If you execute this code, now you can process immediate notifications while the delayed notifications are waiting to be processed.

The problem with this approach is that when you insert a delayed notification the CPU consume is 100% :(

I think I still have to investigate how to work with signals and timers in Windows.
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#include <iostream>
#include <chrono>
#include <thread>
#include <condition_variable>
#include <queue>
#include <atomic>
#include <mutex>
#include <ctime>

static std::queue<int> notifications;
static std::atomic<bool> stopSignal = false;
static std::mutex mutexNotifications;
static std::condition_variable cv;

std::string now()
{
    std::time_t t = std::time(nullptr) ;
    std::string str = std::asctime( std::localtime( std::addressof(t) ) ) ;
    str.pop_back() ;
    return str ;
}

static void push_immediate( int notification_id )
{
    {
        std::lock_guard<std::mutex> lock(mutexNotifications);
        notifications.push(notification_id);
    }

    cv.notify_one();
}

static void push_delayed( int notification_id, int secs_delay = 10 )
{
    std::cout << "delayed push of notification #" << notification_id
              << " generated at " << now() << " (delay: " << secs_delay << " seconds)." << std::endl;

    std::this_thread::sleep_for( std::chrono::seconds(secs_delay) ) ;
    {
        std::lock_guard<std::mutex> lock(mutexNotifications);
        notifications.push(notification_id);
    }

    cv.notify_one();
}

static void run()
{
    while( !stopSignal )
    {
        std::unique_lock<std::mutex> lock(mutexNotifications);
        cv.wait(lock, []
        {
                return( !notifications.empty() || stopSignal );
        });

        if( !notifications.empty() )
        {
            int notification_id = notifications.front();
            notifications.pop();
            std::cout << "Got notification #" << notification_id << " at " << now() << std::endl;
        }
    }
}

int main()
{
    std::thread runThread(run);

    std::cout << "Start typing integers. 1 to start the timer and 0 to finish.\n"
              << "0 or non-digit to quit.\n"
              << "1 to push an immediate notification.\n"
              << "2 to push a delayed notification (5 seconds delay).\n"
              << "3 to push a delayed notification (10 seconds delay).\n\n";

    int notification_id = 0 ;

    while( !stopSignal )
    {
        int input;
        std::cin >> input;

        switch(input)
        {
            case 0 :
                stopSignal = true ;
                cv.notify_one();
                break ;

            case 1 :
                push_immediate( ++notification_id ) ;
                break ;

            case 2 :
                std::thread( push_delayed, ++notification_id, 5 ).detach() ;
                break ;

            case 3 :
                std::thread( push_delayed, ++notification_id, 10 ).detach() ;
                break ;

            default: ; // do nothing
        }
    }

    runThread.join();
}
Hi JLBorges!

Thanks again for your response. Your proposal is good, but I need a solution without using threads, because that would mean to add synchronization mechanism that could be quite complex.

I have been investigation about timers in Windows, and it seems the application must be in an alertable state to be interrupted by the timer. It seems there is no way in Windows that the timer could interrupt my application in the middle of a long running task.

I still need more time to investigate this.

But thanks for your help!
Topic archived. No new replies allowed.