Mac OS C++ | Implement your own timer library | Embedded System | Operating System

AlishS

New Member
Design a software timer handler that triggers a specific function that gets executed when a timeout event occurs. Say there are 10 tasks that come in, each will have a timeout value and each will have a unique function to be called on timeout. You have one HW timer and need to handle this in Software. In case a Compiler is needed.

I implemented the below code, let me know your comments and suggestions.

Code:
#include <iostream>
#include <unistd.h>        /* For Sleep */
#include <pthread.h>    /* To acquire mutex */
#include <queue>        /*To hold all the tasks which needs to be executed */

using namespace std;

void Task1(void) { cout << "Task1 " << endl; }
void Task2(void) { cout << "Task2 " << endl; }
void Task3(void) { cout << "Task3 " << endl; }
void Task4(void) { cout << "Task4 " << endl; }
void Task5(void) { cout << "Task5 " << endl; }

typedef struct {
    bool timer_enable;                     /* Tells if timer is enabled or not */
    bool periodic;                        /* Tells if timer is periodic or not */
    uint32_t reload_timeout_value;        /* Reload value of timer, used in case of periodic timer to reload curr timeout value*/
    uint32_t curr_timeout_value;        /* Curr value of timer */
    void (*Callback)(void);                /* Call Back Function to be called upon timeout */
} TASK_MAPPING;

#define MAX_TASK 5
TASK_MAPPING TimerTask[MAX_TASK];
queue <uint32_t> Task_queue;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

/* TimerInterrupt is called every 1 milli Sec */
void TimerInterrupt() {
    uint32_t timer_index;
    pthread_mutex_lock(&mutex);
    for(timer_index = 0; timer_index < MAX_TASK; timer_index++) {
        if(TimerTask[timer_index].timer_enable == true) {
            if(TimerTask[timer_index].curr_timeout_value == 0) {
                /* Stop the timer, if it is not periodic */
                if(TimerTask[timer_index].periodic == false) {
                    TimerTask[timer_index].timer_enable = false;
                }
                else{
                    /* Reload timer value */
                    TimerTask[timer_index].curr_timeout_value = TimerTask[timer_index].reload_timeout_value;
                }
                /* Put this task into queue */
                Task_queue.push(timer_index);
            }
            else{
                TimerTask[timer_index].curr_timeout_value--;
            }
        }
    }
    pthread_mutex_unlock(&mutex);
}

void timer_start(uint32_t *timerId, void (*pCallback)(void), uint32_t timeout, bool periodic) {
    pthread_mutex_lock(&mutex);
    uint32_t timer_index;
    for(timer_index = 0; timer_index < MAX_TASK; timer_index++) {
        /* Find the empty slot where timer is not enabled */
        if(TimerTask[timer_index].timer_enable == false) {
            /* Enable the timer, with received parameters */
            TimerTask[timer_index].timer_enable = true;
            TimerTask[timer_index].reload_timeout_value = timeout;
            TimerTask[timer_index].curr_timeout_value = timeout;
            TimerTask[timer_index].periodic = periodic;
            TimerTask[timer_index].Callback = pCallback;
            /* Handler Id is used by caller to stop the timer */
            *timerId = timer_index;
            break;
        }
    }
    pthread_mutex_unlock(&mutex);
}

void timer_stop(uint32_t timerId) {
    pthread_mutex_lock(&mutex);
    if(timerId < MAX_TASK) {
        TimerTask[timerId].timer_enable = false;
        TimerTask[timerId].periodic = false;
        TimerTask[timerId].reload_timeout_value = 0xFFFFFFFF;
        TimerTask[timerId].curr_timeout_value = 0xFFFFFFFF;
        TimerTask[timerId].Callback = nullptr;
    }
    pthread_mutex_unlock(&mutex);
}

void *TimerInterrupt(void *arg) {
    /*Generate Timer Interrupt every 1sec */
    static uint32_t counter = 0;
    while(1) {
        cout << counter++ << endl;
        TimerInterrupt();
        sleep(1);
    }
    return nullptr;
}

void *RunTasks(void *arg) {
    while(1) {
        pthread_mutex_lock(&mutex);
        while(!Task_queue.empty()) {
            uint32_t timer_index = Task_queue.front();
            Task_queue.pop();
            TimerTask[timer_index].Callback();
        }
        pthread_mutex_unlock(&mutex);
    }
    return nullptr;
}

void InitTimerTask() {
    uint32_t task_index;
    for(task_index = 0; task_index < MAX_TASK; task_index++) {
        timer_stop(task_index);
    }
}

int main() {
    pthread_t thread_id1;
    pthread_t thread_id2;
    InitTimerTask();
    pthread_create(&thread_id1, NULL, &TimerInterrupt, NULL);
    pthread_create(&thread_id2, NULL, &RunTasks, NULL);

    uint32_t timerId1;
    timer_start(&timerId1, Task1, 3, true);

    uint32_t timerId2;
    timer_start(&timerId2, Task2, 10, true);

    uint32_t timerId3;
    timer_start(&timerId3, Task3, 15, false);

    sleep(60);

    timer_stop(timerId1);
    timer_stop(timerId2);

    pthread_cancel(thread_id1);
    pthread_cancel(thread_id2);

    return 0;
}
 
Good work.

I'm working now on win32 api task and have some difficulties managing "WindowProc" function with its different commnands.
 
Back
Top