poll.c

Cross-platform polling library for C
git clone git://git.finwo.net/lib/poll.c
Log | Files | Refs | README

fpoll.c (3505B)


      1 #include <stddef.h>
      2 #include <stdlib.h>
      3 #include <string.h>
      4 
      5 #include "fpoll.h"
      6 
      7 struct fpoll * fpoll_create() {
      8   struct fpoll *output = calloc(1, sizeof(struct fpoll));
      9   return output;
     10 }
     11 
     12 FPOLL_STATUS fpoll_close(struct fpoll *descriptor) {
     13   if (descriptor->fds  ) free(descriptor->fds);
     14   if (descriptor->udata) free(descriptor->udata);
     15   free(descriptor);
     16   return FPOLL_STATUS_OK;
     17 }
     18 
     19 int fpoll_wait(struct fpoll *descriptor, struct fpoll_ev *evs, int max_evs, int timeout) {
     20   int i, c;
     21 
     22   // Fetch new events
     23   if (!descriptor->remaining) {
     24     descriptor->remaining = poll(descriptor->fds, descriptor->size, timeout);
     25   }
     26 
     27   // Handle remaining events, possibly from previous run
     28   if (descriptor->remaining) {
     29     c = 0;
     30     for( i = 0 ; (i < descriptor->size) && (c < max_evs) ; i++ ) {
     31       if (!(descriptor->fds[i].revents)) continue;
     32 
     33       // Convert event to our standard
     34       evs[c].fd    = descriptor->fds[i].fd;
     35       evs[c].ev    = descriptor->fds[i].revents;
     36       evs[c].udata = descriptor->udata[i];
     37 
     38       // Reset the origin
     39       descriptor->fds[i].revents = 0;
     40 
     41       // Iterate to the next
     42       descriptor->remaining -= 1;
     43       c++;
     44     }
     45 
     46     // Prevent deadlocks
     47     if (i == descriptor->size) {
     48       descriptor->remaining = 0;
     49     }
     50 
     51     return c;
     52   }
     53 
     54   return 0;
     55 }
     56 
     57 FPOLL_STATUS fpoll_add(struct fpoll *descriptor, FPOLL_EVENT events, FPOLL_FD filedescriptor, void *udata) {
     58 
     59   // Initial alloc
     60   if (!descriptor->fds) {
     61     descriptor->limit = 4;
     62     descriptor->fds   = calloc(descriptor->limit, sizeof(struct pollfd));
     63     descriptor->udata = calloc(descriptor->limit, sizeof(void *       ));
     64   }
     65 
     66   // Grow alloc
     67   if (descriptor->limit < (descriptor->size + 1)) {
     68     descriptor->limit = descriptor->limit * 2;
     69     descriptor->fds   = realloc(descriptor->fds  , descriptor->limit * sizeof(struct pollfd));
     70     descriptor->udata = realloc(descriptor->udata, descriptor->limit * sizeof(void *       ));
     71   }
     72 
     73   // Find the filedescriptor in the list
     74   struct pollfd *pfd = NULL;
     75   int i;
     76   for(i = 0 ; i < descriptor->size; i++) {
     77     if (filedescriptor != descriptor->fds[i].fd) continue;
     78     pfd = &(descriptor->fds[i]);
     79     break;
     80   }
     81 
     82   // Assign a new pollfd if needed
     83   if (!pfd) {
     84     descriptor->udata[descriptor->size] = udata;
     85     pfd              = &(descriptor->fds[descriptor->size]);
     86     descriptor->size = descriptor->size + 1;
     87     pfd->fd          = filedescriptor;
     88     pfd->events      = 0;
     89   }
     90 
     91   // Assign the correct events
     92   pfd->events = events;
     93 
     94   return FPOLL_STATUS_OK;
     95 }
     96 
     97 FPOLL_STATUS fpoll_del(struct fpoll *descriptor, FPOLL_EVENT events, FPOLL_FD filedescriptor) {
     98 
     99   // Initial alloc
    100   if (!descriptor->fds) {
    101     descriptor->limit = 4;
    102     descriptor->fds   = calloc(descriptor->limit, sizeof(struct pollfd));
    103   }
    104 
    105   // Find the filedescriptor in the list
    106   struct pollfd *pfd = NULL;
    107   int i;
    108   for(i = 0 ; i < descriptor->size; i++) {
    109     if (filedescriptor != descriptor->fds[i].fd) continue;
    110     pfd = &(descriptor->fds[i]);
    111     break;
    112   }
    113 
    114   // Remove marked events
    115   if (pfd) {
    116     pfd->events &= ~events;
    117 
    118     // Remove fd from list if it has no events
    119     if (!pfd->events) {
    120       if ((i + 1) < descriptor->size) {
    121         memmove(&(descriptor->fds[i]  ), &(descriptor->fds[i+1]  ), (descriptor->size - i) * sizeof(struct pollfd));
    122         memmove(&(descriptor->udata[i]), &(descriptor->udata[i+1]), (descriptor->size - i) * sizeof(void *       ));
    123       }
    124       descriptor->size -= 1;
    125     }
    126   }
    127 
    128   return FPOLL_STATUS_OK;
    129 }