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 }