Function MQ_startTimer
This function starts a timer. When the given time runs out, the callback will be invoked, unless the timer is stopped first with MQ_stopTimer.
/**
* Start a timer
*
* @param context the context to start the timer in
* @param timeout the number of seconds to wait before invoking the callback
* @param callback the callback to invoke when the timer runs out
* @param data customer user data to provide to the callback
*/
MQ_Timer *MQ_startTimer(MQ_Context *context, float timeout, void(*callback)(void *data), void *data);
Using timer functionality, we can amend the example for the MQ_ioWatch function so that it times out when no input is entered for at least five seconds.
#include <mailerq.h>
#include <string.h>
#include <stdio.h>
/**
* Structure that references both timers
*/
struct Timers
{
/**
* The IO watcher
*/
MQ_IOWatcher *io;
/**
* The timer
*/
MQ_Timer *timer;
};
/**
* Callback function to receive standard input
*
* @param watcher the watcher that is monitoring the file descriptor
* @param fd the file descriptor that received events
* @param data custom data pointer
*/
void io_callback(MQ_IOWatcher *watcher, int fd, int events, void *data)
{
// buffer for data to process
char data[1024];
ssize_t length;
// retrieve the timers
struct Timers *timers = (struct Timers*)data;
// we are working with STDIN, which is never writable
// (because that's what we have STDOUT for), so we don't
// have to check the events variable, otherwise we could
// check for readability or writability like this:
//
// events & MQ_READ
// events & MQ_WRITE
// normally, when we check for readability we should not
// assume that we are receiving complete lines, however
// STDIN is line-buffered, so the callback is only invoked
// whenever the user presses return after input
// read data from input
length = read(fd, data, sizeof(data));
// if there are only two characters we received an empty line
// since the line includes the CRLF produced by the terminal
if (length == 2)
{
// stop watching the file descriptor
MQ_ioUnwatch(watcher);
// deactive the timer
MQ_stopTimer(timers->timer);
// clean up the timers
free(timers);
}
else
{
// reset the timer to five seconds
MQ_resetTimer(timers->timer, 5.0);
}
}
/**
* Callback function for an expiring timer
*
* @param data custom user data
*/
void timer_callback(void *data)
{
// get the timers
struct Timers *timers = (struct Timers*)data;
// we did not receive any input for 5 seconds
// so we stop listening to input
MQ_ioUnwatch(timers->io);
// and free the timers
free(timers);
}
/**
* Monitor standard input for data
*
* @param context the context to monitor in
*/
void monitor(MQ_Context *context)
{
// create the structure holding the timers
Timers *timers = malloc(sizeof(struct Timers));
// set the context
timers->context = context;
// monitor stdin for input
timers.io = MQ_ioWatch(context, STDIN, MQ_READ, callback, timers);
// and stop monitoring after five seconds
timers.timer = MQ_startTimer(context, 5.0, timer_callback, timers);
}