Overview

Timer is a mechanism to perform some periodic action. Potential use cases are:

  • Sending heartbeat messages to the connectied clients
  • Implementing reconnection logic for MQTT or Websocket clients
  • Periodic upload of the telemetry data
  • Periodic version checking for software updates

Architecture

Timer API is tiny and consists of a few key components:

struct mg_timer

This structure holds the housekeeping information - timer interval, a function to call, and function argument. NOTE: this structure must be pre-allocated by user - either statically, or on stack, or by calling malloc(). This structure must be alive during the lifetime of a timer.

Timer API

When a timer gets created, a flags argument controls its bevahior:

  • MG_TIMER_REPEAT - call function fn periodically every period_ms milliseconds. If that flag is not specified, then a timer is one-off
  • MG_TIMER_RUN_NOW - call function fn immediately after timer creation

Example

Every initialised timer gets added to the global list g_timers. This snippet of code initialises a timer that simply logs a message. We allocate timer structure on stack in the main() function.

#include "mongoose.h"

static void timer_fn(void *arg) {
  LOG(LL_INFO, ("Timer function called, arg %p", arg));
}

int main(void) {
  struct mg_mgr mgr;
  struct mg_timer t;
  mg_mgr_init(&mgr);
  mg_timer_init(&t, 300, MG_TIMER_REPEAT, timer_fn, &mgr);  // 300ms interval
  for (int i = 0; i < 500; i++) mg_mgr_poll(&mgr, 10);      // Work 5 seconds
  mg_timer_free(&t);
  mg_mgr_free(&mgr);
  return 0;
}

This program intialises on-stack timer, which has 300ms interval. In this program, there is no call to the mg_timer_poll() function - because mg_mgr_poll() function calls mg_timer_poll() that iterates over the global list of timers g_timers.