to myself 的分类学习日志

做自己想做的事
posts - 232, comments - 6, trackbacks - 0, articles - 0

/*
 * ev.h
 
*/

#ifndef EV_H_
#define EV_H_

#define EV_FEATURES 0x7f

#define EV_FEATURE_CONFIG   ((EV_FEATURES) &  4)

#define EV_MINPRI (EV_FEATURE_CONFIG ? -2 : 0)
#define EV_MAXPRI (EV_FEATURE_CONFIG ? +2 : 0)

#define NUMPRI (EV_MAXPRI - EV_MINPRI + 1)

#define ABSPRI(w) (((W)w)->priority - EV_MINPRI)
#define EV_CB_INVOKE(watcher, revents) (watcher)->cb ((watcher), (revents))

#define EMPTY2(a,b) /* used to suppress some warnings */


/************* watcher related ***********************/
typedef struct ev_watcher
{
    int active;
    int pending;
    int priority;
    void *data;
    void (*cb)(struct ev_watcher *w, int revents);
    struct ev_watcher *next;
} ev_watcher;

typedef ev_watcher *W;


typedef struct ev_watcher_list
{
    int active;
    int pending;
    int priority;
    void *data;
    void (*cb)(struct ev_watcher_list *w, int revents);
    struct ev_watcher_list *next;
} ev_watcher_list;

typedef ev_watcher_list *WL;


/* invoked when fd is either EV_READable or EV_WRITEable */
/* revent EV_READ, EV_WRITE */
typedef struct ev_io
{
    int active;
    int pending;
    int priority;
    void *data;
    void (*cb)(struct ev_io *w, int revents);
    struct ev_io *next;

    int fd; /* ro */
    int events; /* ro */
} ev_io;


/* stores the pending event set for a given watcher */
typedef struct
{
  W w;
  int events; /* the pending event set for the given watcher */
} ANPENDING;

int pendingpri;
int pendingcnt[NUMPRI];
ANPENDING *pendings [NUMPRI]; // save pending events
int pendingmax [NUMPRI];


/**************** ANFD related ****************************/
/* set in reify when reification needed */
#define EV_ANFD_REIFY 1

/* file descriptor info structure */
typedef struct
{
  WL head;
  unsigned char events; /* the events watched for */
  unsigned char reify;  /* flag set when this ANFD needs reification (EV_ANFD_REIFY, EV__IOFDSET) */
  unsigned char emask;  /* the epoll backend stores the actual kernel mask in here */
  unsigned char unused;
  unsigned int egen;    /* generation counter to counter epoll bugs */
} ANFD;

ANFD * anfds// save all events
int anfdmax;

int * fdchanges;
int fdchangemax;
int fdchangecnt;


/***************** function interface *****************************/
void fd_event(int fd, int revents);
void ev_invoke_pending();


void ev_io_start (ev_io *w);
void ev_io_stop (ev_io *w);


#endif /* EV_H_ */


#include "ev.h"
#include <stdio.h>
#include <stdlib.h>

/*****************************************************************************/
void * ev_realloc (void *ptr, long size)
{
    ptr = realloc(ptr, size);

    if (!ptr && size)
    {
        abort();
    }

    return ptr;
}

#define MALLOC_ROUND 4096 /* prefer to allocate in chunks of this size, must be 2**n and >> 4 longs */

/* find a suitable new size for the given array, */
/* hopefully by rounding to a nice-to-malloc size */
int array_nextsize (int elem, int cur, int cnt)
{
  int ncur = cur + 1;

  do
    ncur <<= 1;
  while (cnt > ncur);

  /* if size is large, round to MALLOC_ROUND - 4 * longs to accommodate malloc overhead */
  if (elem * ncur > MALLOC_ROUND - sizeof (void *) * 4)
    {
      ncur *= elem;
      ncur = (ncur + elem + (MALLOC_ROUND - 1) + sizeof (void *) * 4) & ~(MALLOC_ROUND - 1);
      ncur = ncur - sizeof (void *) * 4;
      ncur /= elem;
    }

  return ncur;
}

static void * array_realloc (int elem, void *baseint *cur, int cnt)
{
  *cur = array_nextsize (elem, *cur, cnt);
  return ev_realloc (base, elem * *cur);
}

#define array_init_zero(base,count)    \
  memset ((void *)(base), 0, sizeof (*(base)) * (count))

#define array_needsize(type,base,cur,cnt,init)            \
  if (0 != ((cnt) > (cur)))                \
    {                                \
      int ocur_ = (cur);                    \
      (base) = (type *)array_realloc                \
         (sizeof (type), (base), &(cur), (cnt));        \
      init ((base) + (ocur_), (cur) - ocur_);            \
    }

#define array_free(stem, idx) \
  ev_free (stem ## s idx); stem ## cnt idx = stem ## max idx = 0; stem ## s idx = 0

/*****************************************************************************/
void ev_invoke_pending()
{
    pendingpri = NUMPRI;

    while (pendingpri) /* pendingpri possibly gets modified in the inner loop */
    {
        --pendingpri;

        while (pendingcnt[pendingpri])
        {
            ANPENDING *p = pendings[pendingpri] + --pendingcnt[pendingpri];

            p->w->pending = 0;
            EV_CB_INVOKE(p->w, p->events);
        }
    }
}


void ev_feed_event(void *w, int revents)
{
    W w_ = (W) w;
    int pri = ABSPRI(w_);

    if (0 != (w_->pending))
    {
        pendings[pri][w_->pending - 1].events |= revents;
    }
    else
    {
        w_->pending = ++pendingcnt[pri];
        array_needsize(ANPENDING, pendings[pri], pendingmax[pri],
                w_->pending, EMPTY2);
        pendings[pri][w_->pending - 1].w = w_;
        pendings[pri][w_->pending - 1].events = revents;
    }

    pendingpri = NUMPRI - 1;
}


void fd_event_nocheck(int fd, int revents)
{
    ANFD *anfd = anfds + fd;
    ev_io *w;

    for (w = (ev_io *) anfd->head; w; w = (ev_io *) ((WL) w)->next)
    {
        int ev = w->events & revents;

        if (ev)
            ev_feed_event((W) w, ev);
    }
}


/* do not submit kernel events for fds that have reify set */
/* because that means they changed while we were polling for new events */
void fd_event(int fd, int revents)
{
  ANFD *anfd = anfds + fd;

  if (!anfd->reify)
    fd_event_nocheck(fd, revents);
}



void wlist_add (WL *head, WL elem)
{
  elem->next = *head;
  *head = elem;
}

void wlist_del (WL *head, WL elem)
{
  while (*head)
    {
      if (*head == elem)
        {
          *head = elem->next;
          break;
        }

      head = &(*head)->next;
    }
}

void ev_io_start (ev_io *w)
{
  int fd = w->fd;

  array_needsize (ANFD, anfds, anfdmax, fd + 1, array_init_zero);
  wlist_add (&anfds[fd].head, (WL)w);
}

void ev_io_stop (ev_io *w)
{
  wlist_del (&anfds[w->fd].head, (WL)w);
}


/*
 * test.c
 *
 
*/
#include "ev.h"
#include <stdio.h>

void test_cb(struct ev_watcher *w, int revents)
{
    printf("test_cb\n");
}

// 1 fd -> multi events(or event watcher)
// epoll_poll -> fd_event -> fd_event_nocheck -> ev_feed_event -> ev_invoke_pending
int main(int aargc, char *argv[])
{
    ev_io w_io;
    w_io.active = 1;
    w_io.pending = 0;
    w_io.priority = 2;
    w_io.data = 0;
    w_io.cb = test_cb;
    w_io.next = 0;
    w_io.fd = 10;
    w_io.events = 2;
    ev_io_start(&w_io); // register event


    int fd = 10;
    int revents = 2;
    fd_event(fd, revents); // discover event


    ev_invoke_pending(); // raise event

    return 0;
}












只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理