scheduler.c

Basic task scheduling library
git clone git://git.finwo.net/lib/scheduler.c
Log | Files | Refs | README | LICENSE

scheduler.c (2254B)


      1 #include "scheduler.h"
      2 
      3 #include <stdlib.h>
      4 #include <sys/select.h>
      5 #include <sys/time.h>
      6 
      7 #ifndef NULL
      8 #define NULL ((void *)0)
      9 #endif
     10 
     11 pt_task_t    *pt_first = NULL;
     12 fd_set        g_select_result;
     13 static fd_set g_want_fds;
     14 
     15 pt_task_t *sched_create(pt_task_fn fn, void *udata) {
     16   if (!fn) return NULL;
     17 
     18   pt_task_t *node = calloc(1, sizeof(pt_task_t));
     19   node->next      = pt_first;
     20   node->func      = fn;
     21   node->udata     = udata;
     22   node->is_active = 1;
     23   pt_first        = node;
     24 
     25   return node;
     26 }
     27 
     28 int sched_remove(pt_task_t *task) {
     29   if (!task) return 1;
     30 
     31   pt_task_t *curr = pt_first;
     32   pt_task_t *prev = NULL;
     33 
     34   while (curr) {
     35     if (curr == task) {
     36       if (prev) {
     37         prev->next = curr->next;
     38       } else {
     39         pt_first = curr->next;
     40       }
     41       free(curr);
     42       return 0;
     43     }
     44     prev = curr;
     45     curr = curr->next;
     46   }
     47 
     48   return 1;
     49 }
     50 
     51 int sched_has_data(int *in_fds) {
     52   if (!in_fds || in_fds[0] == 0) return -1;
     53 
     54   for (int i = 1; i <= in_fds[0]; i++) {
     55     int fd = in_fds[i];
     56     if (fd >= 0) {
     57       FD_SET(fd, &g_want_fds);
     58     }
     59   }
     60 
     61   for (int i = 1; i <= in_fds[0]; i++) {
     62     int fd = in_fds[i];
     63     if (fd >= 0 && FD_ISSET(fd, &g_select_result)) {
     64       FD_CLR(fd, &g_select_result);
     65       return fd;
     66     }
     67   }
     68 
     69   return -1;
     70 }
     71 
     72 int sched_main(void) {
     73   if (!pt_first) return 0;
     74 
     75   struct timeval tv;
     76   int            maxfd;
     77 
     78   for (;;) {
     79     maxfd = -1;
     80     for (int fd = 0; fd < FD_SETSIZE; fd++) {
     81       if (FD_ISSET(fd, &g_want_fds)) {
     82         if (fd > maxfd) maxfd = fd;
     83       }
     84     }
     85 
     86     if (maxfd < 0) {
     87       tv.tv_sec  = 0;
     88       tv.tv_usec = 100000;
     89       select(0, NULL, NULL, NULL, &tv);
     90     } else {
     91       tv.tv_sec  = 0;
     92       tv.tv_usec = 100000;
     93       select(maxfd + 1, &g_want_fds, NULL, NULL, &tv);
     94       g_select_result = g_want_fds;
     95       FD_ZERO(&g_want_fds);
     96     }
     97 
     98     struct timeval now;
     99     gettimeofday(&now, NULL);
    100     int64_t timestamp = (int64_t)now.tv_sec * 1000 + now.tv_usec / 1000;
    101 
    102     pt_task_t *task = pt_first;
    103     while (task) {
    104       pt_task_t *next = task->next;
    105       task->is_active = (task->func(timestamp, task) == SCHED_RUNNING);
    106       if (!task->is_active) {
    107         sched_remove(task);
    108       }
    109       task = next;
    110     }
    111 
    112     if (!pt_first) break;
    113   }
    114 
    115   return 0;
    116 }