Ejemplo n.º 1
0
static int
poll_dispatch(struct event_base *base, struct timeval *tv)
{
	int res, i, j, nfds;
	long msec = -1;
	struct pollop *pop = base->evbase;
	struct pollfd *event_set;

	poll_check_ok(pop);

	nfds = pop->nfds;

#ifndef EVENT__DISABLE_THREAD_SUPPORT
	if (base->th_base_lock) {
		/* If we're using this backend in a multithreaded setting,
		 * then we need to work on a copy of event_set, so that we can
		 * let other threads modify the main event_set while we're
		 * polling. If we're not multithreaded, then we'll skip the
		 * copy step here to save memory and time. */
		if (pop->realloc_copy) {
			struct pollfd *tmp = mm_realloc(pop->event_set_copy,
			    pop->event_count * sizeof(struct pollfd));
			if (tmp == NULL) {
				event_warn("realloc");
				return -1;
			}
			pop->event_set_copy = tmp;
			pop->realloc_copy = 0;
		}
		memcpy(pop->event_set_copy, pop->event_set,
		    sizeof(struct pollfd)*nfds);
		event_set = pop->event_set_copy;
	} else {
		event_set = pop->event_set;
	}
#else
	event_set = pop->event_set;
#endif

	if (tv != NULL) {
		msec = evutil_tv_to_msec_(tv);
		if (msec < 0 || msec > INT_MAX)
			msec = INT_MAX;
	}

	EVBASE_RELEASE_LOCK(base, th_base_lock);

	res = poll(event_set, nfds, msec);

	EVBASE_ACQUIRE_LOCK(base, th_base_lock);

	if (res == -1) {
		if (errno != EINTR) {
			event_warn("poll");
			return (-1);
		}

		return (0);
	}

	event_debug(("%s: poll reports %d", __func__, res));

	if (res == 0 || nfds == 0)
		return (0);

	i = evutil_weakrand_range_(&base->weakrand_seed, nfds);
	for (j = 0; j < nfds; j++) {
		int what;
		if (++i == nfds)
			i = 0;
		what = event_set[i].revents;
		if (!what)
			continue;

		res = 0;

		/* If the file gets closed notify */
		if (what & (POLLHUP|POLLERR|POLLNVAL))
			what |= POLLIN|POLLOUT;
		if (what & POLLIN)
			res |= EV_READ;
		if (what & POLLOUT)
			res |= EV_WRITE;
		if (res == 0)
			continue;

		evmap_io_active_(base, event_set[i].fd, res);
	}

	return (0);
}
Ejemplo n.º 2
0
int
win32_dispatch(struct event_base *base, struct timeval *tv)
{
	struct win32op *win32op = base->evbase;
	int res = 0;
	unsigned j, i;
	int fd_count;
	SOCKET s;

	if (win32op->resize_out_sets) {
		size_t size = FD_SET_ALLOC_SIZE(win32op->num_fds_in_fd_sets);
		if (!(win32op->readset_out = mm_realloc(win32op->readset_out, size)))
			return (-1);
		if (!(win32op->exset_out = mm_realloc(win32op->exset_out, size)))
			return (-1);
		if (!(win32op->writeset_out = mm_realloc(win32op->writeset_out, size)))
			return (-1);
		win32op->resize_out_sets = 0;
	}

	fd_set_copy(win32op->readset_out, win32op->readset_in);
	fd_set_copy(win32op->exset_out, win32op->writeset_in);
	fd_set_copy(win32op->writeset_out, win32op->writeset_in);

	fd_count =
	    (win32op->readset_out->fd_count > win32op->writeset_out->fd_count) ?
	    win32op->readset_out->fd_count : win32op->writeset_out->fd_count;

	if (!fd_count) {
		long msec = tv ? evutil_tv_to_msec_(tv) : LONG_MAX;
		/* Sleep's DWORD argument is unsigned long */
		if (msec < 0)
			msec = LONG_MAX;
		/* Windows doesn't like you to call select() with no sockets */
		Sleep(msec);
		return (0);
	}

	EVBASE_RELEASE_LOCK(base, th_base_lock);

	res = select(fd_count,
		     (struct fd_set*)win32op->readset_out,
		     (struct fd_set*)win32op->writeset_out,
		     (struct fd_set*)win32op->exset_out, tv);

	EVBASE_ACQUIRE_LOCK(base, th_base_lock);

	event_debug(("%s: select returned %d", __func__, res));

	if (res <= 0) {
		return res;
	}

	if (win32op->readset_out->fd_count) {
		i = evutil_weakrand_range_(&base->weakrand_seed,
		    win32op->readset_out->fd_count);
		for (j=0; j<win32op->readset_out->fd_count; ++j) {
			if (++i >= win32op->readset_out->fd_count)
				i = 0;
			s = win32op->readset_out->fd_array[i];
			evmap_io_active_(base, s, EV_READ);
		}
	}
	if (win32op->exset_out->fd_count) {
		i = evutil_weakrand_range_(&base->weakrand_seed,
		    win32op->exset_out->fd_count);
		for (j=0; j<win32op->exset_out->fd_count; ++j) {
			if (++i >= win32op->exset_out->fd_count)
				i = 0;
			s = win32op->exset_out->fd_array[i];
			evmap_io_active_(base, s, EV_WRITE);
		}
	}
	if (win32op->writeset_out->fd_count) {
		SOCKET s;
		i = evutil_weakrand_range_(&base->weakrand_seed,
		    win32op->writeset_out->fd_count);
		for (j=0; j<win32op->writeset_out->fd_count; ++j) {
			if (++i >= win32op->writeset_out->fd_count)
				i = 0;
			s = win32op->writeset_out->fd_array[i];
			evmap_io_active_(base, s, EV_WRITE);
		}
	}
	return (0);
}
Ejemplo n.º 3
0
static int
select_dispatch(struct event_base *base, struct timeval *tv)
{
	int res=0, i, j, nfds;
	struct selectop *sop = base->evbase;

	check_selectop(sop);
	if (sop->resize_out_sets) {
		fd_set *readset_out=NULL, *writeset_out=NULL;
		size_t sz = sop->event_fdsz;
		if (!(readset_out = mm_realloc(sop->event_readset_out, sz)))
			return (-1);
		sop->event_readset_out = readset_out;
		if (!(writeset_out = mm_realloc(sop->event_writeset_out, sz))) {
			/* We don't free readset_out here, since it was
			 * already successfully reallocated. The next time
			 * we call select_dispatch, the realloc will be a
			 * no-op. */
			return (-1);
		}
		sop->event_writeset_out = writeset_out;
		sop->resize_out_sets = 0;
	}

	memcpy(sop->event_readset_out, sop->event_readset_in,
	       sop->event_fdsz);
	memcpy(sop->event_writeset_out, sop->event_writeset_in,
	       sop->event_fdsz);

	nfds = sop->event_fds+1;

	EVBASE_RELEASE_LOCK(base, th_base_lock);

	res = select(nfds, sop->event_readset_out,
	    sop->event_writeset_out, NULL, tv);

	EVBASE_ACQUIRE_LOCK(base, th_base_lock);

	check_selectop(sop);

	if (res == -1) {
		if (errno != EINTR) {
			event_warn("select");
			return (-1);
		}

		return (0);
	}

	event_debug(("%s: select reports %d", __func__, res));

	check_selectop(sop);
	i = evutil_weakrand_range_(&base->weakrand_seed, nfds);
	for (j = 0; j < nfds; ++j) {
		if (++i >= nfds)
			i = 0;
		res = 0;
		if (FD_ISSET(i, sop->event_readset_out))
			res |= EV_READ;
		if (FD_ISSET(i, sop->event_writeset_out))
			res |= EV_WRITE;

		if (res == 0)
			continue;

		evmap_io_active_(base, i, res);
	}
	check_selectop(sop);

	return (0);
}