0
没有什么可说的!一切全在代码里!



//封装的epoll

static GObjectClass *parent_class = NULL;

#if HAVE_EPOLL_SUPPORT

#include <sys/epoll.h>
#include <errno.h>

/* epoll_create() etc based main-loop.

  Note that we use Level-Triggered behavior,
  not edge-triggered, since that is how GskMainLoops are.
*/

#define EPOLL_INITIAL_SIZE 2048
#define MAX_EPOLL_EVENTS 512

static inline const char *
op_to_string (int op)
{
 return (op == EPOLL_CTL_DEL) ? "del"
      : (op == EPOLL_CTL_MOD) ? "mod"
      : (op == EPOLL_CTL_ADD) ? "add"
      : "op-unknown";
}

/* --- GskMainLoopPollBase methods --- */
static gboolean
gsk_main_loop_epoll_setup  (GskMainLoop       *main_loop)
{
 GskMainLoopClass *pclass = GSK_MAIN_LOOP_CLASS (parent_class);
 int fd;
 if (pclass->setup != NULL)
   if (!(*pclass->setup) (main_loop))
     return FALSE;
 fd = epoll_create (EPOLL_INITIAL_SIZE);
 if (fd < 0)
   return FALSE;
 GSK_MAIN_LOOP_EPOLL (main_loop)->fd = fd;
 return TRUE;
}

static void
gsk_main_loop_epoll_config_fd (GskMainLoopPollBase   *main_loop,
                              int                    fd,
         GIOCondition           old_io_conditions,
                              GIOCondition           io_conditions)
{
 GskMainLoopEpoll *epoll = GSK_MAIN_LOOP_EPOLL (main_loop);
 int op = (io_conditions == 0) ? EPOLL_CTL_DEL
        : (old_io_conditions == 0) ? EPOLL_CTL_ADD
 : EPOLL_CTL_MOD;
 struct epoll_event event;
 if (old_io_conditions == 0 && io_conditions == 0)
   return;
 event.events = ((io_conditions & G_IO_IN) ? (EPOLLIN) : 0)
              | ((io_conditions & G_IO_OUT) ? (EPOLLOUT) : 0)
              | ((io_conditions & G_IO_HUP) ? (EPOLLHUP) : 0)
       ;
 event.data.fd = fd;
 if (epoll_ctl (epoll->fd, op, fd, &event) < 0)
   {
     g_warning ("epoll_ctl: op=%s, fd=%d, new_events=%x failed: %s",
  op_to_string (op), fd, event.events, g_strerror (errno));
   }
}

static gboolean
gsk_main_loop_epoll_do_polling (GskMainLoopPollBase   *main_loop,
                               int                    max_timeout,
                               guint                  max_events,
                               guint                 *num_events_out,
                               GskMainLoopEvent      *events)
{
 GskMainLoopEpoll *main_loop_epoll = GSK_MAIN_LOOP_EPOLL (main_loop);
 struct epoll_event *e_events = main_loop_epoll->epoll_events;
 int n_events;
 int i;
 guint n_out = 0;
 errno = EINTR;  // HACK: ignore errors which don't set errno !?!
 n_events = epoll_wait (main_loop_epoll->fd, e_events,
   MIN (max_events, MAX_EPOLL_EVENTS),
   max_timeout);
#if 0
 g_message ("epoll_wait: max_timeout=%d, max_events=%u, n_events out=%d",
     max_timeout, max_events, n_events);
#endif
 if (n_events < 0)
   {
     int e = errno;
     *num_events_out = 0;
     if (gsk_errno_is_ignorable (e))
return TRUE;
     g_warning ("error running epoll_wait: %s", g_strerror (e));
     return TRUE;
   }

 for (i = 0; i < n_events; i++)
   {
     int fd = e_events[i].data.fd;
     unsigned e = e_events[i].events;
     GIOCondition condition = 0;
     if (e & EPOLLIN)
condition |= G_IO_IN;
     if (e & EPOLLHUP)
condition |= G_IO_HUP;
     if (e & EPOLLOUT)
condition |= G_IO_OUT;
     events[n_out].type = GSK_MAIN_LOOP_EVENT_IO;
     events[n_out].data.io.events = condition;
     events[n_out].data.io.fd = fd;
     n_out++;
   }
 *num_events_out = n_out;

 return TRUE;
}

static void
gsk_main_loop_epoll_finalize (GObject *object)
{
 GskMainLoopEpoll *main_loop_epoll = GSK_MAIN_LOOP_EPOLL (object);
 g_free (main_loop_epoll->epoll_events);
 (*parent_class->finalize) (object);
}
#endif  /* HAVE_EPOLL_SUPPORT */

/* --- functions --- */
static void
gsk_main_loop_epoll_init (GskMainLoopEpoll *main_loop_epoll)
{
#if HAVE_EPOLL_SUPPORT
 main_loop_epoll->fd = -1;
 main_loop_epoll->epoll_events = g_new (struct epoll_event, MAX_EPOLL_EVENTS);
#endif  /* HAVE_EPOLL_SUPPORT */
}

static void
gsk_main_loop_epoll_class_init (GskMainLoopEpollClass *class)
{
#if HAVE_EPOLL_SUPPORT
 GskMainLoopPollBaseClass *main_loop_poll_base_class = GSK_MAIN_LOOP_POLL_BASE_CLASS (class);
 GskMainLoopClass *main_loop_class = GSK_MAIN_LOOP_CLASS (class);
 GObjectClass *object_class = G_OBJECT_CLASS (class);
 main_loop_class->setup = gsk_main_loop_epoll_setup;
 main_loop_poll_base_class->config_fd = gsk_main_loop_epoll_config_fd;
 main_loop_poll_base_class->do_polling = gsk_main_loop_epoll_do_polling;
 object_class->finalize = gsk_main_loop_epoll_finalize;
#endif  /* HAVE_EPOLL_SUPPORT */
 parent_class = g_type_class_peek_parent (class);
}

GType gsk_main_loop_epoll_get_type()
{
 static GType main_loop_epoll_type = 0;
 if (!main_loop_epoll_type)
   {
     static const GTypeInfo main_loop_epoll_info =
     {
sizeof(GskMainLoopEpollClass),
(GBaseInitFunc) NULL,
(GBaseFinalizeFunc) NULL,
(GClassInitFunc) gsk_main_loop_epoll_class_init,
NULL,  /* class_finalize */
NULL,  /* class_data */
sizeof (GskMainLoopEpoll),
0,  /* n_preallocs */
(GInstanceInitFunc) gsk_main_loop_epoll_init,
NULL  /* value_table */
     };
     main_loop_epoll_type = g_type_register_static (GSK_TYPE_MAIN_LOOP_POLL_BASE,
                                                 "GskMainLoopEpoll",
       &main_loop_epoll_info, 0);
   }
 return main_loop_epoll_type;
}


//封装的kqueue


static GObjectClass *parent_class = NULL;

#if HAVE_KQUEUE
#include <signal.h>

/* Include headers for kqueue(), kevent() and struct kevent. */
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
#endif

#include <unistd.h>    /* needed for close() */
#include <string.h>

/* --- GskMainLoop methods --- */

static gboolean
gsk_main_loop_kqueue_setup (GskMainLoop *main_loop)
{
 GskMainLoopKqueue *main_loop_kqueue = GSK_MAIN_LOOP_KQUEUE (main_loop);
#if HAVE_KQUEUE
 main_loop_kqueue->kernel_queue_id = kqueue ();
 return (main_loop_kqueue->kernel_queue_id >= 0);
#else
 (void) main_loop_kqueue;
 return FALSE;
#endif
}

#if HAVE_KQUEUE
static void
kqueue_flush_pending_changes (GskMainLoopKqueue *main_loop_kqueue)
{
 if (main_loop_kqueue->num_updates > 0)
   {
     struct timespec timeout = { 0, 0 };
     kevent (main_loop_kqueue->kernel_queue_id,
             (const struct kevent *) main_loop_kqueue->kevent_array,
      main_loop_kqueue->num_updates,
      NULL, 0,
             &timeout);
     main_loop_kqueue->num_updates = 0;
   }
}

static inline void
change_signal (int signo, gboolean ignore)
{
 struct sigaction action;
 memset (&action, 0, sizeof (action));
 action.sa_handler = ignore ? SIG_IGN : SIG_DFL;
 sigaction (signo, &action, NULL);
}

static inline struct kevent *
get_next_update ( GskMainLoopKqueue *main_loop_kqueue)
{
 if (main_loop_kqueue->num_updates == main_loop_kqueue->max_updates)
   {
     if (main_loop_kqueue->max_updates == 0)
       main_loop_kqueue->max_updates = 128;
     else
       main_loop_kqueue->max_updates *= 2;
     main_loop_kqueue->kevent_array
= g_realloc (main_loop_kqueue->kevent_array,
      sizeof (struct kevent) * main_loop_kqueue->max_updates);
   }
 return ((struct kevent *) (main_loop_kqueue->kevent_array))
       + main_loop_kqueue->num_updates;
}
 

static void
gsk_main_loop_kqueue_change (GskMainLoop       *main_loop,
                            GskMainLoopChange *change)
{
 GskMainLoopKqueue *main_loop_kqueue = GSK_MAIN_LOOP_KQUEUE (main_loop);
 if (main_loop_kqueue->num_updates + 1 >= main_loop_kqueue->max_updates)
   {
     if (main_loop_kqueue->max_updates == 0)
       main_loop_kqueue->max_updates = 128;
     else
       main_loop_kqueue->max_updates *= 2;
     main_loop_kqueue->kevent_array
= g_realloc (main_loop_kqueue->kevent_array,
      sizeof (struct kevent) * main_loop_kqueue->max_updates);
   }
 switch (change->type)
   {
     static gboolean has_ignored_sigchld = FALSE;
     struct kevent *event;
   case GSK_MAIN_LOOP_EVENT_PROCESS:
     if (change->data.process.did_exit)
       return;
     event = get_next_update (main_loop_kqueue);
     event->ident = change->data.process.pid;
     event->filter = EVFILT_PROC;
     event->flags = change->data.process.add ? (EV_ADD|EV_ONESHOT|EV_CLEAR) : EV_DELETE;
     event->fflags = NOTE_EXIT;
     event->data = 0;
     event->udata = NULL;
     main_loop_kqueue->num_updates++;
     if (!has_ignored_sigchld)
       {
         change_signal (SIGCHLD, TRUE);
         has_ignored_sigchld = TRUE;
       }
     break;
   case GSK_MAIN_LOOP_EVENT_SIGNAL:
     event = get_next_update (main_loop_kqueue);
     event->ident = change->data.signal.number;
     event->filter = EVFILT_SIGNAL;
     event->flags = change->data.signal.add ? EV_ADD : EV_DELETE;
     event->fflags = 0;
     event->data = 0;
     event->udata = NULL;
     change_signal (change->data.signal.number, change->data.signal.add);
     main_loop_kqueue->num_updates++;
     kqueue_flush_pending_changes (main_loop_kqueue);
     break;
   case GSK_MAIN_LOOP_EVENT_IO:
     if ((change->data.io.old_events ^ change->data.io.events) & G_IO_IN)
{
         event = get_next_update (main_loop_kqueue);
  event->ident = change->data.io.fd;
  event->filter = EVFILT_READ;
  event->flags = (change->data.io.events & G_IO_IN) ? EV_ADD : EV_DELETE;
  event->fflags = 0;
  event->data = 0;
  event->udata = NULL;
  main_loop_kqueue->num_updates++;
}
     if ((change->data.io.old_events ^ change->data.io.events) & G_IO_OUT)
{
         event = get_next_update (main_loop_kqueue);
  event->ident = change->data.io.fd;
  event->filter = EVFILT_WRITE;
  event->flags = (change->data.io.events & G_IO_OUT) ? EV_ADD : EV_DELETE;
  event->fflags = 0;
  event->data = 0;
  event->udata = NULL;
  main_loop_kqueue->num_updates++;
}
     kqueue_flush_pending_changes (main_loop_kqueue);
     break;
   }
}

static guint
gsk_main_loop_kqueue_poll (GskMainLoop       *main_loop,
                          guint              max_events_out,
                          GskMainLoopEvent  *events,
                          gint               timeout_milli)
{
 struct kevent *out = alloca (sizeof (struct kevent) * max_events_out);
 GskMainLoopKqueue *main_loop_kqueue = GSK_MAIN_LOOP_KQUEUE (main_loop);
 guint kevent_rv;
 guint i;
 guint rv = 0;
 struct timespec timeout;
 struct timespec *p_timeout;
 if (timeout_milli < 0)
   {
     p_timeout = NULL;
   }
 else
   {
     timeout.tv_sec = timeout_milli / 1000;
     timeout.tv_nsec = timeout_milli % 1000 * 1000 * 1000;
     p_timeout = &timeout;
   }
 kevent_rv = kevent (main_loop_kqueue->kernel_queue_id,
       main_loop_kqueue->kevent_array,
       main_loop_kqueue->num_updates,
       out,
       max_events_out,
       p_timeout);
 main_loop_kqueue->num_updates = 0;

 for (i = 0; i < kevent_rv; i++)
   {
     switch (out[i].filter)
       {
       case EVFILT_READ:
         events[rv].type = GSK_MAIN_LOOP_EVENT_IO;
         events[rv].data.io.events = G_IO_IN;
         events[rv].data.io.fd = out[i].ident;
         rv++;
         break;
         
       case EVFILT_WRITE:
         events[rv].type = GSK_MAIN_LOOP_EVENT_IO;
         events[rv].data.io.events = G_IO_OUT;
         events[rv].data.io.fd = out[i].ident;
         rv++;
         break;

       case EVFILT_SIGNAL:
         events[rv].type = GSK_MAIN_LOOP_EVENT_SIGNAL;
         events[rv].data.signal = out[i].ident;
         rv++;
         break;

       case EVFILT_PROC:
         if (out[i].fflags == NOTE_EXIT)
           {
             events[rv].type = GSK_MAIN_LOOP_EVENT_PROCESS;
             events[rv].data.process_wait_info.pid = out[i].ident;
             if (gsk_main_loop_do_waitpid (out[i].ident,
                                        &events[rv].data.process_wait_info))
               rv++;
           }
         break;

       default:
         g_warning ("unexpected type of event from kevent (%d)",
                    out[i].filter);
       }
   }
 return rv;
}
#endif

static void    
gsk_main_loop_kqueue_finalize(GObject *object)
{
 GskMainLoopKqueue *kqueue = GSK_MAIN_LOOP_KQUEUE (object);
 gsk_main_loop_destroy_all_sources (GSK_MAIN_LOOP (object));
 if (kqueue->kernel_queue_id >= 0)
   close (kqueue->kernel_queue_id);
 (*parent_class->finalize) (object);
}

/* --- class methods --- */
static void
gsk_main_loop_kqueue_init (GskMainLoopKqueue *kqueue)
{
 kqueue->kernel_queue_id = -1;
}

static void
gsk_main_loop_kqueue_class_init (GskMainLoopClass *main_loop_class)
{
 GObjectClass *object_class = G_OBJECT_CLASS (main_loop_class);
 parent_class = g_type_class_peek_parent (main_loop_class);
 main_loop_class->setup = gsk_main_loop_kqueue_setup;
#if HAVE_KQUEUE
 main_loop_class->poll = gsk_main_loop_kqueue_poll;
 main_loop_class->change = gsk_main_loop_kqueue_change;
#endif
 object_class->finalize = gsk_main_loop_kqueue_finalize;
}

GType
gsk_main_loop_kqueue_get_type()
{
 static GType main_loop_kqueue_type = 0;
 if (!main_loop_kqueue_type)
   {
     static const GTypeInfo main_loop_kqueue_info =
     {
sizeof(GskMainLoopKqueueClass),
(GBaseInitFunc) NULL,
(GBaseFinalizeFunc) NULL,
(GClassInitFunc) gsk_main_loop_kqueue_class_init,
NULL,  /* class_finalize */
NULL,  /* class_data */
sizeof (GskMainLoopKqueue),
0,  /* n_preallocs */
(GInstanceInitFunc) gsk_main_loop_kqueue_init,
NULL  /* value_table */
     };
     GType parent = GSK_TYPE_MAIN_LOOP;
     main_loop_kqueue_type = g_type_register_static (parent,
                                                 "GskMainLoopKqueue",
       &main_loop_kqueue_info, 0);
   }
 return main_loop_kqueue_type;
}

Tags: , , , | 引用(0)
发表评论
表情
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
打开HTML
打开UBB
打开表情
隐藏
记住我
昵称   密码   游客无需密码
网址   电邮   [注册]