iPadDevloperJr
iPadDevloperJr

Reputation: 1004

C timers and threads again

Can someone help me to complete my code with a function that can check the result of a timer "check_timer" and another one that reset this timer if it had expired "reset_timer"?

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <errno.h>
#include <sys/time.h>

#define GLOBAL_TIMER  8 * 60 * 60


typedef struct protocol_type {
 int protocol_number;
 char *protocol_name;
 pthread_t thread_timer_id;
} protocol_type_t;

pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;


/* call back function - inform the user the time has expired */
void timeout_call_back(pthread_t thread_id)
{
    printf("Welcome thread %ld, your time is up ===\n", pthread_self());
    // doing some other stuff
}

/* Go to sleep for a period of seconds */
static void* start_timer(void *args)
{
    /* function pointer */
    void (*finish_function)(pthread_t);


    int seconds = *((int*) args);

    finish_function = timeout_call_back;

 struct timeval now;
 struct timespec timeout;

 pthread_mutex_lock(&mut);
 printf("thread ID : %ld, are waiting for %d seconds to to expire\n", pthread_self(), seconds);
 gettimeofday(&now, NULL);
 timeout.tv_sec = now.tv_sec + seconds;
 timeout.tv_nsec = now.tv_usec * 1000;
 pthread_cond_timedwait(&cond, &mut, &timeout);
 (*finish_function)(pthread_self());
 pthread_mutex_unlock(&mut);
    pthread_exit(NULL);
}

// This function is in MT environnement and is running inside a daemon
int received_buffer_parser(char *received_buffer) {
 pthread_mutex_t mut_main = PTHREAD_MUTEX_INITIALIZER; 
 protocol_type_t *my_protocol;

 // Identify protocol type
 my_protocol = protocol_identifier(received_buffer);

 // Check if i received it in the last 8 hours in safe 
 pthread_mutex_lock(&mut_main);
    if (check_timer(my_protocol->thread_id) has expired) { // I want to write this function
  // I want to reset thread timer
   launch_new_timer(my_protocol->thread_id)
 }
 else {
  // doing some stuff
  // dump data to the disk
 }
 pthread_mutex_unlock(&mut_main);

 return 0;
}

int launch_new_timer(pthread_t thread_id)
{
 int rc;
 int seconds = GLOBAL_TIMER;

    rc =  pthread_create(&thread_id, NULL, start_timer, (void *) &seconds);
    if(rc)
     printf("Failed to create thread1\n");

    pthread_join(thread_id, NULL);

    return 0;
}

Clarification

I clarify here the real context of my code: I receive from the network some types of different protocols packets(ICMP, SSH, RIP, OSPF, BGP...), and i want to:

  1. identify every type of packets, let say with : identify_protocol(char *received_buffer), I got this function, it's ok.

  2. Check if i receive this type of protocols in the last 8 hours (THE TIMER OF EACH PROTOCOL TYPE EXPIRE AFTER 8 HOURS), two choices:

a. if so, I dump the result data into a specific file on the disk.

b. no, I didn't receive this type in the last 8 HOURS i create a new thread (in my code i simplify, with thread1, thread2 and thread3, this threads are 3 threads used to be a timers for three protocols types) - i start a new timer with : start_timer(void *args) function do this job.

My main question is how to be able to check the result of my timers in a safe manner and then decide i reset the timer or not.

I design the finish_function at the beginning to help me to check when the timer has expired.

Feel free to give me a better design for best performances for my program.

My system is Linux.

Upvotes: 1

Views: 12356

Answers (1)

Martin v. L&#246;wis
Martin v. L&#246;wis

Reputation: 127537

To check for timers that merely expire, you don't need to use threads and synchronization at all. Simply keep global variables indicating the start time of the timer. So

  • when the timer starts, set a global variable (one per protocol) to gettimeofday()
  • when you want to check whether the timer has expired for a protocol, see whether gettimeofday()-starttime(protocol) is <8h

If you want to be notified on timer expiry, I recommend to use alarm(2). It only has second resolution, but that should be good enough for 8h timeouts. Whenever a timer is set, cancelled, or reset, compute the minimum timeout of any of the timers, then call alarm with that timeout. In the signal handler, perform the processing that you want to do on reception of timeout. Alternatively, do nothing in the signal handler, and just trust that any pending system call will be interrupted, and check all timers for expiry on EINTR.

Edit: alarm works like this

#include <unistd.h>
#include <signal.h>
void timeout(int ignored)
{
   printf("timed out\n");
}

void main()
{
    signal(SIGALRM, timeout);
    alarm(10);
    pause();
}

Upvotes: 3

Related Questions