Logo Search packages:      
Sourcecode: rageircd version File versions  Download package

engine_poll.c

/*
 * RageIRCd: an advanced Internet Relay Chat daemon (ircd).
 * (C) 2000-2005 the RageIRCd Development Team, all rights reserved.
 *
 * This software is free, licensed under the General Public License.
 * Please refer to doc/LICENSE and doc/README for further details.
 *
 * $Id: engine_poll.c,v 1.24.2.1 2004/12/07 03:05:10 pneumatus Exp $
 */

#include "setup.h"
#include "struct.h"
#include "common.h"
#include "sys.h"
#include "h.h"
#include "fd.h"

#ifdef USE_POLL

#include POLLH

#ifndef POLLRDNORM
#define POLLRDNORM POLLIN
#endif
#ifndef POLLWRNORM
#define POLLWRNORM POLLOUT
#endif

typedef struct _pollfd_list pollfd_list;
struct _pollfd_list {
      struct pollfd list[MAXCONNECTIONS];
      int max_index;
};

static pollfd_list poll_fds;

static int poll_find_slot()
{
      int i;

      for (i = 0; i < MAXCONNECTIONS; i++) {
            if (poll_fds.list[i].fd == FD_UNUSED) {
                  return i;
            }
      }

      ASSERT("poll_find_slot() with no slots" == NULL);
      return FD_UNUSED;
}

static void poll_update_fds(int fd, short event, FDCB *cb)
{
      fd_entry *fde = &fd_table[fd];
      int i;

      if (fde->index == FD_UNUSED) {
            fde->index = poll_find_slot();
      }

      i = fde->index;

      if (cb != NULL) {
            poll_fds.list[i].events |= event;
            poll_fds.list[i].fd = fd;

            if (i > poll_fds.max_index) {
                  poll_fds.max_index = i;
            }
      }
      else if (i >= 0) {
            poll_fds.list[i].events &= ~event;

            if (poll_fds.list[i].events) {
                  return;
            }

            poll_fds.list[i].fd = FD_UNUSED;
            poll_fds.list[i].revents = 0;
            fde->index = FD_UNUSED;

            if (i == poll_fds.max_index) {
                  while ((poll_fds.max_index >= 0)
                    && (poll_fds.list[poll_fds.max_index].fd == FD_UNUSED)) {
                        poll_fds.max_index--;
                  }
            }
      }
}

void engine_init()
{
      int i;

      for (i = 0; i < MAXCONNECTIONS; i++) {
            poll_fds.list[i].fd = FD_UNUSED;
            poll_fds.list[i].events = 0;
            poll_fds.list[i].revents = 0;
      }

      poll_fds.max_index = 0;
}

void engine_set_call(int fd, unsigned short flags, FDCB *cb, void *data, time_t timeout)
{
      fd_entry *fde = &fd_table[fd];

      if (flags & FDEV_READ) {
            SetCallback(fde->read, cb, data);
            poll_update_fds(fd, POLLRDNORM, cb);
      }
      if (flags & FDEV_WRITE) {
            SetCallback(fde->write, cb, data);
            poll_update_fds(fd, POLLWRNORM, cb);
      }
      if (timeout) {
            fde->timeout_time = timeofday + (timeout / 1000);
      }
}

void engine_do_netio(time_t delay)
{
      int cnt, i, fd;
      fd_entry *fde;
      FDCB *cb;
      void *data;

      for (;;) {
            if ((cnt = poll(poll_fds.list, poll_fds.max_index + 1, delay)) >= 0) {
                  break;
            }
            if (engine_ignore_errno(errno)) {
                  continue;
            }

            set_time();
            return;
      }

      set_time();

      if (!cnt) {
            return;
      }

      for (i = 0; i < poll_fds.max_index + 1; i++) {
            if (!poll_fds.list[i].revents || (poll_fds.list[i].fd == FD_UNUSED)) {
                  continue;
            }

            fd = poll_fds.list[i].fd;
            fde = &fd_table[fd];

            if (poll_fds.list[i].revents & (POLLRDNORM|POLLIN|POLLHUP|POLLERR)) {
                  GetCallback(fde->read, cb, data);
                  ClrCallback(fde->read);

                  poll_update_fds(fd, POLLRDNORM, NULL);

                  if (cb != NULL) {
                        cb(fd, data, ENGINE_OK);
                  }
            }

            if (poll_fds.list[i].revents & (POLLWRNORM|POLLOUT|POLLHUP|POLLERR)) {
                  GetCallback(fde->write, cb, data);
                  ClrCallback(fde->write);

                  poll_update_fds(fd, POLLWRNORM, NULL);

                  if (cb != NULL) {
                        cb(fd, data, ENGINE_OK);
                  }
            }
      }
}

#endif

Generated by  Doxygen 1.6.0   Back to index