Chinaunix首页 | 论坛 | 博客
  • 博客访问: 276350
  • 博文数量: 95
  • 博客积分: 618
  • 博客等级: 中士
  • 技术积分: 455
  • 用 户 组: 普通用户
  • 注册时间: 2011-03-28 13:39
文章分类

全部博文(95)

文章存档

2015年(65)

2013年(1)

2012年(10)

2011年(19)

分类: C/C++

2015-08-16 23:48:39

event.h

点击(此处)折叠或打开

  1. #ifndef _EVENT_H_
  2. #define _EVENT_H_

  3. #define EVLIST_TIMEOUT    0x01
  4. #define EVLIST_READ    0x02
  5. #define EVLIST_WRITE    0x04
  6. #define EVLIST_ADD    0x08
  7. #define EVLIST_INIT    0x80

  8. #define EV_TIMEOUT    EVLIST_TIMEOUT
  9. #define EV_READ        EVLIST_READ
  10. #define EV_WRITE    EVLIST_WRITE

  11. struct event {
  12.     struct {
  13.         struct event *tqe_next;    /* next element */
  14.         struct event **tqe_prev;    /* address of previous next element */
  15.     }ev_read_next;
  16.     
  17.     struct {
  18.         struct event *tqe_next;    /* next element */
  19.         struct event **tqe_prev;    /* address of previous next element */
  20.     }ev_write_next;
  21.     
  22.     struct {
  23.         struct event *tqe_next;    /* next element */
  24.         struct event **tqe_prev;    /* address of previous next element */
  25.     }ev_timeout_next;
  26.     
  27.     struct {
  28.         struct event *tqe_next;    /* next element */
  29.         struct event **tqe_prev;    /* address of previous next element */
  30.     }ev_add_next;

  31.     int ev_fd;
  32.     short ev_events;

  33.     struct timeval ev_timeout;

  34.     void (*ev_callback)(int, short, void *arg);
  35.     void *ev_arg;

  36.     int ev_flags;
  37. };

  38. #define TIMEOUT_DEFAULT    5

  39. void event_init(void);
  40. int event_dispatch(void);

  41. int timeout_next(struct timeval *);
  42. void timeout_process(void);

  43. #define timeout_add(ev, tv)        event_add(ev, tv)
  44. #define timeout_set(ev, cb, arg)    event_set(ev, -1, 0, cb, arg)
  45. #define timeout_del(ev)            event_del(ev)
  46. #define timeout_pending(ev, tv)        event_pending(ev, EV_TIMEOUT, tv)
  47. #define timeout_initalized(ev)        ((ev)->ev_flags & EVLIST_INIT)

  48. void event_set(struct event *, int, short, void (*)(int, short, void *), void *);
  49. void event_add(struct event *, struct timeval *);
  50. void event_del(struct event *);

  51. int event_pending(struct event *, short, struct timeval *);

  52. #define event_initalized(ev)        ((ev)->ev_flags & EVLIST_INIT)

  53. #endif /* _EVENT_H_ */
event.c


点击(此处)折叠或打开

  1. #include <sys/types.h>
  2. #include <sys/time.h>
  3. #include <sys/queue.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <unistd.h>
  7. #include <errno.h>
  8. #include <string.h>

  9. #ifdef USE_LOG
  10. #include "log.h"
  11. #else
  12. #define LOG_DBG(x)
  13. #define log_error(x)    perror(x)
  14. #endif

  15. #include "event.h"

  16. #ifndef howmany
  17. #define howmany(x, y) (((x)+((y)-1))/(y))
  18. #endif

  19. /* Prototypes */
  20. void event_add_post(struct event *);

  21. struct timeout_list {
  22.     struct event *tqh_first;    /* first element */    
  23.     struct event **tqh_last;    /* addr of last next element */
  24. }timequeue;

  25. struct event_wlist {
  26.     struct event *tqh_first;    /* first element */    
  27.     struct event **tqh_last;    /* addr of last next element */
  28. }writequeue;

  29. struct event_rlist {
  30.     struct event *tqh_first;    /* first element */    
  31.     struct event **tqh_last;    /* addr of last next element */
  32. }readqueue;

  33. struct event_ilist {
  34.     struct event *tqh_first;    /* first element */    
  35.     struct event **tqh_last;    /* addr of last next element */
  36. }addqueue;

  37. int event_inloop = 0;
  38. int event_fds;        /* Highest fd in fd set */
  39. int event_fdsz;
  40. fd_set *event_readset;
  41. fd_set *event_writeset;

  42. void
  43. event_init(void)
  44. {
  45.     (&timequeue)->tqh_first = NULL;                    
  46.     (&timequeue)->tqh_last = &(&timequeue)->tqh_first;
  47.     
  48.     (&writequeue)->tqh_first = NULL;                    
  49.     (&writequeue)->tqh_last = &(&writequeue)->tqh_first;
  50.     
  51.     (&readqueue)->tqh_first = NULL;                    
  52.     (&readqueue)->tqh_last = &(&readqueue)->tqh_first;
  53.     
  54.     (&addqueue)->tqh_first = NULL;                    
  55.     (&addqueue)->tqh_last = &(&addqueue)->tqh_first;;
  56. }

  57. /*
  58.  * Called with the highest fd that we know about. If it is 0, completely
  59.  * recalculate everything.
  60.  */

  61. int
  62. events_recalc(int max)
  63. {
  64.     fd_set *readset, *writeset;
  65.     struct event *ev;
  66.     int fdsz;

  67.     event_fds = max;

  68.     if (!event_fds) {
  69.         
  70.     //TAILQ_FOREACH(ev, &writequeue, ev_write_next)
  71.         for(ev = TAILQ_FIRST(&writequeue);
  72.                 ev != TAILQ_END(&writequeue);
  73.                 ev = TAILQ_NEXT(ev,ev_write_next))
  74.         {
  75.             if (ev->ev_fd > event_fds)
  76.                 event_fds = ev->ev_fd;
  77.         }
  78.         for(ev = TAILQ_FIRST(&readqueue);
  79.              ev != TAILQ_END(&readqueue);
  80.              ev = TAILQ_NEXT(ev, ev_read_next))
  81.         {
  82.             if (ev->ev_fd > event_fds)
  83.                 event_fds = ev->ev_fd;
  84.         }
  85.     }

  86.     fdsz = howmany(event_fds + 1, NFDBITS) * sizeof(fd_mask);
  87.     if (fdsz > event_fdsz) {
  88.         if ((readset = realloc(event_readset, fdsz)) == NULL) {
  89.             log_error("malloc");
  90.             return (-1);
  91.         }

  92.         if ((writeset = realloc(event_writeset, fdsz)) == NULL) {
  93.             log_error("malloc");
  94.             free(readset);
  95.             return (-1);
  96.         }

  97.         memset(readset + event_fdsz, 0, fdsz - event_fdsz);
  98.         memset(writeset + event_fdsz, 0, fdsz - event_fdsz);

  99.         event_readset = readset;
  100.         event_writeset = writeset;
  101.         event_fdsz = fdsz;
  102.     }

  103.     return (0);
  104. }

  105. int
  106. event_dispatch(void)
  107. {
  108.     struct timeval tv;
  109.     struct event *ev, *old;
  110.     int res, maxfd;

  111.     /* Calculate the initial events that we are waiting for */
  112.     if (events_recalc(0) == -1)
  113.         return (-1);

  114.     while (1) {
  115.         memset(event_readset, 0, event_fdsz);
  116.         memset(event_writeset, 0, event_fdsz);
  117. //        TAILQ_FOREACH(var, head, field)    
  118. //    for((var) = TAILQ_FIRST(head);(var) != TAILQ_END(head);(var) = TAILQ_NEXT(var, field))
  119.         for(ev = TAILQ_FIRST(&writequeue);
  120.                 ev != TAILQ_END(&writequeue);
  121.                 ev = TAILQ_NEXT(ev, ev_write_next))
  122.         {
  123.                 FD_SET(ev->ev_fd, event_writeset);
  124.         }
  125.         for(ev = TAILQ_FIRST(&readqueue);
  126.                 ev != TAILQ_END(&readqueue);
  127.                 ev = TAILQ_NEXT(ev, ev_read_next))
  128.         {
  129.                 FD_SET(ev->ev_fd, event_readset);
  130.         }

  131.         timeout_next(&tv);

  132.         if ((res = select(event_fds + 1, event_readset,
  133.                  event_writeset, NULL, &tv)) == -1) {
  134.             if (errno != EINTR) {
  135.                 log_error("select");
  136.                 return (-1);
  137.             }
  138.             continue;
  139.         }

  140.         LOG_DBG((LOG_MISC, 80, __FUNCTION__": select reports %d",
  141.              res));

  142.         maxfd = 0;
  143.         event_inloop = 1;
  144.         for (ev = TAILQ_FIRST(&readqueue); ev;) {
  145.             old = TAILQ_NEXT(ev, ev_read_next);
  146.             if (FD_ISSET(ev->ev_fd, event_readset)) {
  147.                 event_del(ev);
  148.                 (*ev->ev_callback)(ev->ev_fd, EV_READ,
  149.                          ev->ev_arg);
  150.             } else if (ev->ev_fd > maxfd)
  151.                 maxfd = ev->ev_fd;

  152.             ev = old;
  153.         }

  154.         for (ev = TAILQ_FIRST(&writequeue); ev;) {
  155.             old = TAILQ_NEXT(ev, ev_read_next);
  156.             if (FD_ISSET(ev->ev_fd, event_writeset)) {
  157.                 event_del(ev);
  158.                 (*ev->ev_callback)(ev->ev_fd, EV_WRITE,
  159.                          ev->ev_arg);
  160.             } else if (ev->ev_fd > maxfd)
  161.                 maxfd = ev->ev_fd;

  162.             ev = old;
  163.         }
  164.         event_inloop = 0;

  165.         for (ev = TAILQ_FIRST(&addqueue); ev;
  166.          ev = TAILQ_FIRST(&addqueue)) {
  167.             TAILQ_REMOVE(&addqueue, ev, ev_add_next);
  168.             ev->ev_flags &= ~EVLIST_ADD;
  169.             
  170.             event_add_post(ev);

  171.             if (ev->ev_fd > maxfd)
  172.                 maxfd = ev->ev_fd;
  173.         }

  174.         if (events_recalc(maxfd) == -1)
  175.             return (-1);

  176.         timeout_process();
  177.     }

  178.     return (0);
  179. }

  180. void
  181. event_set(struct event *ev, int fd, short events,
  182.      void (*callback)(int, short, void *), void *arg)
  183. {
  184.     ev->ev_callback = callback;
  185.     ev->ev_arg = arg;
  186.     ev->ev_fd = fd;
  187.     ev->ev_events = events;
  188.     ev->ev_flags = EVLIST_INIT;
  189. }

  190. /*
  191.  * Checks if a specific event is pending or scheduled.
  192.  */

  193. int
  194. event_pending(struct event *ev, short event, struct timeval *tv)
  195. {
  196.     int flags = ev->ev_flags;

  197.     /*
  198.      * We might not have been able to add it to the actual queue yet,
  199.      * check if we will enqueue later.
  200.      */
  201.     if (ev->ev_flags & EVLIST_ADD)
  202.         flags |= (ev->ev_events & (EV_READ|EV_WRITE));

  203.     event &= (EV_TIMEOUT|EV_READ|EV_WRITE);

  204.     /* See if there is a timeout that we should report */
  205.     if (tv != NULL && (flags & event & EV_TIMEOUT))
  206.         *tv = ev->ev_timeout;

  207.     return (flags & event);
  208. }

  209. void
  210. event_add(struct event *ev, struct timeval *tv)
  211. {
  212.     LOG_DBG((LOG_MISC, 55,
  213.          "event_add: event: %p, %s%s%scall %p",
  214.          ev,
  215.          ev->ev_events & EV_READ ? "EV_READ " : " ",
  216.          ev->ev_events & EV_WRITE ? "EV_WRITE " : " ",
  217.          tv ? "EV_TIMEOUT " : " ",
  218.          ev->ev_callback));
  219.     if (tv != NULL) {
  220.         struct timeval now;
  221.         struct event *tmp;

  222.         gettimeofday(&now, NULL);
  223.         timeradd(&now, tv, &ev->ev_timeout);

  224.         LOG_DBG((LOG_MISC, 55,
  225.              "event_add: timeout in %d seconds, call %p",
  226.              tv->tv_sec, ev->ev_callback));
  227.         if (ev->ev_flags & EVLIST_TIMEOUT)
  228.             TAILQ_REMOVE(&timequeue, ev, ev_timeout_next);

  229.         /* Insert in right temporal order */
  230.         for (tmp = TAILQ_FIRST(&timequeue); tmp;
  231.          tmp = TAILQ_NEXT(tmp, ev_timeout_next)) {
  232.          if (timercmp(&ev->ev_timeout, &tmp->ev_timeout, <=))
  233.              break;
  234.         }

  235.         if (tmp)
  236.             TAILQ_INSERT_BEFORE(tmp, ev, ev_timeout_next);
  237.         else
  238.             TAILQ_INSERT_TAIL(&timequeue, ev, ev_timeout_next);

  239.         ev->ev_flags |= EVLIST_TIMEOUT;
  240.     }

  241.     if (event_inloop) {
  242.         /* We are in the event loop right now, we have to
  243.          * postpone the change until later.
  244.          */
  245.         if (ev->ev_flags & EVLIST_ADD)
  246.             return;

  247.         TAILQ_INSERT_TAIL(&addqueue, ev, ev_add_next);
  248.         ev->ev_flags |= EVLIST_ADD;
  249.     } else
  250.         event_add_post(ev);
  251. }

  252. void
  253. event_add_post(struct event *ev)
  254. {
  255.     if ((ev->ev_events & EV_READ) && !(ev->ev_flags & EVLIST_READ)) {
  256.         TAILQ_INSERT_TAIL(&readqueue, ev, ev_read_next);
  257.         
  258.         ev->ev_flags |= EVLIST_READ;
  259.     }
  260.     
  261.     if ((ev->ev_events & EV_WRITE) && !(ev->ev_flags & EVLIST_WRITE)) {
  262.         TAILQ_INSERT_TAIL(&writequeue, ev, ev_write_next);
  263.         
  264.         ev->ev_flags |= EVLIST_WRITE;
  265.     }
  266. }

  267. void
  268. event_del(struct event *ev)
  269. {
  270.     LOG_DBG((LOG_MISC, 80, "event_del: %p, callback %p",
  271.          ev, ev->ev_callback));

  272.     if (ev->ev_flags & EVLIST_ADD) {
  273.         TAILQ_REMOVE(&addqueue, ev, ev_add_next);

  274.         ev->ev_flags &= ~EVLIST_ADD;
  275.     }

  276.     if (ev->ev_flags & EVLIST_TIMEOUT) {
  277.         TAILQ_REMOVE(&timequeue, ev, ev_timeout_next);

  278.         ev->ev_flags &= ~EVLIST_TIMEOUT;
  279.     }

  280.     if (ev->ev_flags & EVLIST_READ) {
  281.         TAILQ_REMOVE(&readqueue, ev, ev_read_next);

  282.         ev->ev_flags &= ~EVLIST_READ;
  283.     }

  284.     if (ev->ev_flags & EVLIST_WRITE) {
  285.         TAILQ_REMOVE(&writequeue, ev, ev_write_next);

  286.         ev->ev_flags &= ~EVLIST_WRITE;
  287.     }
  288. }

  289. int
  290. timeout_next(struct timeval *tv)
  291. {
  292.     struct timeval now;
  293.     struct event *ev;

  294.     if ((ev = TAILQ_FIRST(&timequeue)) == NULL) {
  295.         timerclear(tv);
  296.         tv->tv_sec = TIMEOUT_DEFAULT;
  297.         return (0);
  298.     }

  299.     if (gettimeofday(&now, NULL) == -1)
  300.         return (-1);

  301.     if (timercmp(&ev->ev_timeout, &now, <=)) {
  302.         timerclear(tv);
  303.         return (0);
  304.     }

  305.     timersub(&ev->ev_timeout, &now, tv);

  306.     LOG_DBG((LOG_MISC, 60, "timeout_next: in %d seconds", tv->tv_sec));
  307.     return (0);
  308. }

  309. void
  310. timeout_process(void)
  311. {
  312.     struct timeval now;
  313.     struct event *ev;

  314.     gettimeofday(&now, NULL);

  315.     while ((ev = TAILQ_FIRST(&timequeue)) != NULL) {
  316.         if (timercmp(&ev->ev_timeout, &now, >))
  317.             break;

  318.         TAILQ_REMOVE(&timequeue, ev, ev_timeout_next);
  319.         ev->ev_flags &= ~EVLIST_TIMEOUT;

  320.         LOG_DBG((LOG_MISC, 60, "timeout_process: call %p",
  321.              ev->ev_callback));
  322.         (*ev->ev_callback)(ev->ev_fd, EV_TIMEOUT, ev->ev_arg);
  323.     }
  324. }
event-test.c

点击(此处)折叠或打开

  1. #include <sys/types.h>
  2. #include <sys/stat.h>
  3. #include <sys/queue.h>
  4. #include <sys/time.h>
  5. #include <fcntl.h>
  6. #include <stdlib.h>
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <unistd.h>
  10. #include <errno.h>

  11. #include <event.h>

  12. void
  13. fifo_read(int fd, short event, void *arg)
  14. {
  15.     char buf[255];
  16.     int len;
  17.     struct event *ev = arg;

  18.     /* Reschedule this event */
  19.     event_add(ev, NULL);

  20.     fprintf(stderr, "fifo_read called with fd: %d, event: %d, arg: %p\n",
  21.         fd, event, arg);

  22.     len = read(fd, buf, sizeof(buf) - 1);
  23.     if (len == -1) {
  24.         perror("read");
  25.         return;
  26.     } else if (len == 0) {
  27.         fprintf(stderr, "Connection closed\n");
  28.         return;
  29.     }

  30.     buf[len] = '\0';
  31.     fprintf(stdout, "Read: %s\n", buf);
  32. }

  33. int
  34. main (int argc, char **argv)
  35. {
  36.     struct stat st;
  37.     char *fifo = "event.fifo";
  38.     int socket;
  39.     struct event evfifo;
  40.  
  41.     if (lstat (fifo, &st) == 0) {
  42.         if ((st.st_mode & S_IFMT) == S_IFREG) {
  43.             errno = EEXIST;
  44.             perror("lstat");
  45.             exit (1);
  46.         }
  47.     }

  48.     unlink (fifo);
  49.     if (mkfifo (fifo, 0600) == -1) {
  50.         perror("mkfifo");
  51.         exit (1);
  52.     }

  53.     /* Linux pipes are broken, we need O_RDWR instead of O_RDONLY */
  54. #ifdef __linux
  55.     socket = open (fifo, O_RDWR | O_NONBLOCK, 0);
  56. #else
  57.     socket = open (fifo, O_RDONLY | O_NONBLOCK, 0);
  58. #endif

  59.     if (socket == -1) {
  60.         perror("open");
  61.         exit (1);
  62.     }

  63.     fprintf(stderr, "Write data to %s\n", fifo);

  64.     /* Initalize the event library */
  65.     event_init();

  66.     /* Initalize one event */
  67.     event_set(&evfifo, socket, EV_READ, fifo_read, &evfifo);

  68.     /* Add it to the active events, without a timeout */
  69.     event_add(&evfifo, NULL);
  70.     
  71.     event_dispatch();

  72.     return (0);
  73. }

阅读(1438) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~