⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 poller_kqueue.cc

📁 实现了poll/epoll/devpoll等C++封装
💻 CC
字号:
/*  Poller_kqueue - FreeBSD 4.1 kernel queue wrapper class *  Copyright (C) 2000 Michael R. Elkins <me@sigpipe.org> * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#if HAVE_KQUEUE#include <stdlib.h>#include <string.h>#include "Poller_kqueue.h"#include "dprint.h"/* returns 0 on success, or E* if an error occurs */int Poller_kqueue::init(void){	// initialize a kernel queue for use by the class	mKernelQueue = kqueue();	if(mKernelQueue == -1)		return errno;	// initialize everything to zero	mNumChanges = 0;	mMaxChanges = 0;	mNumResults = 0;	mChanges = 0;	mResults = 0;	mNumFds = 0;	mMaxFds = 0;	mCurResult = 0;	Poller::init();	return 0;	// success}void Poller_kqueue::shutdown(void){	/* kernel queue events are automatically deleted when the socket is	 * closed, so we don't need to do anything special.	 */	if(mChanges != 0) {		free(mChanges);		mChanges = 0;	}	if(mResults != 0) {		free(mResults);		mResults = 0;	}	mNumResults = 0;	mNumChanges = 0;	mMaxChanges = 0;	mNumFds = 0;	Poller::shutdown();}int Poller_kqueue::add(int fd, Client *client, short eventmask){	if(mNumFds == mMaxFds) {		mMaxFds += 128;		/* note that we allocate 2* the amount since each event		 * is returned separately		 */		mResults = (struct kevent*)realloc(mResults, 2 * sizeof(struct kevent) * mMaxFds);	}	mNumFds++;	return setMaskInternal(fd, eventmask, client);}int Poller_kqueue::del(int fd){	if (mNumFds == 0) { 		return EINVAL;	// oops, one too many ::del() calls	}	if (mNumChanges + 2 > mMaxChanges) {		mMaxChanges += 128;		mChanges = (struct kevent*)realloc(mChanges, sizeof(struct kevent) * mMaxChanges);	}	struct kevent *ke;	ke = &mChanges[mNumChanges++];	ke->ident = fd;	ke->filter = EVFILT_READ;	ke->flags = EV_DELETE;	ke = &mChanges[mNumChanges++];	ke->ident = fd;	ke->filter = EVFILT_WRITE;	ke->flags = EV_DELETE;	mNumFds--;	return 0;}int Poller_kqueue::setMaskInternal(int fd, short eventmask, Client *client){	struct kevent *ke;	if(mNumChanges + 2 > mMaxChanges) {		mMaxChanges += 128;		mChanges=(struct kevent*)realloc(mChanges,sizeof(struct kevent) * mMaxChanges);	}	if (eventmask & POLLIN) {		ke = &mChanges[mNumChanges++];		memset(ke, 0, sizeof(struct kevent));		ke->ident = fd;		ke->filter = EVFILT_READ;		ke->flags = EV_ADD | EV_ENABLE;		if (client)			ke->udata = client;	}	if (eventmask & POLLOUT) {		//printf("Poller_kqueue::setMaskInternal : setting write on fd %d\n", fd);		ke = &mChanges[mNumChanges++];		memset(ke, 0, sizeof(struct kevent));		ke->ident = fd;		ke->filter = EVFILT_WRITE;		ke->flags = EV_ADD | EV_ENABLE;		if (client)			ke->udata = client;	}	return 0;}int Poller_kqueue::clearMaskInternal(int fd, short eventmask){	struct kevent *ke;	if(mNumChanges + 2 > mMaxChanges) {		mMaxChanges += 128;		mChanges=(struct kevent*)realloc(mChanges,sizeof(struct kevent) * mMaxChanges);	}	if (!(eventmask & POLLIN)) {		ke = &mChanges[mNumChanges++];		memset(ke, 0, sizeof(struct kevent));		ke->ident = fd;		ke->filter = EVFILT_READ;		ke->flags = EV_DELETE;	}	if (!(eventmask & POLLOUT)) {		ke = &mChanges[mNumChanges++];		memset(ke, 0, sizeof(struct kevent));		ke->ident = fd;		ke->filter = EVFILT_WRITE;		ke->flags = EV_DELETE;	}	return 0;}int Poller_kqueue::setMask(int fd, short eventmask){	int n;	n = setMaskInternal(fd, eventmask, 0);	if (n)		return n;	/* clear the unset bit(s).  this might not actually be set	 * but to avoid keeping state we just attempt to unset it	 * anyway	 */	n = clearMaskInternal(fd, eventmask);	if (n)		return n;	return 0;}int Poller_kqueue::orMask(int fd, short eventmask){	return setMaskInternal(fd, eventmask, 0);}int Poller_kqueue::andMask(int fd, short eventmask){	return clearMaskInternal(fd, eventmask);}int Poller_kqueue::waitForEvents(int timeout_millisec){	struct timespec to;	if (timeout_millisec >= 0) {		to.tv_sec = timeout_millisec / 1000;		to.tv_nsec = (timeout_millisec % 1000) * 1000000;	// nanosec	}/*	printf("Poller_kqueue::waitForEvents : %d changes\n",		mNumChanges);	printf("Poller_kqueue::waitForEvents : %d fds\n",		mNumFds);	for(int i=0; i < mNumChanges; i++) {		printf("Poller_kqueue::waitForEvents : fd=%d filt=%d flags=%d\n",			mChanges[i].ident,			mChanges[i].filter,			mChanges[i].flags);	}*/	mNumResults = kevent(mKernelQueue, mChanges, mNumChanges,			mResults, 2*mMaxFds,			(timeout_millisec >= 0) ? &to : (struct timespec *) 0);	mCurResult = 0;	mNumChanges = 0;	// reset	if(mNumResults == -1) {		int err = errno;		DPRINT(("Poller_kqueue::waitForEvents : kevent : %s (errno %d)\n",			strerror(err), err));		return err;	}/*	printf("Poller_kqueue::waitForEvents : %d pending events\n",		mNumResults);*/	if(mNumResults == 0)		return EWOULDBLOCK;	return 0;}int Poller_kqueue::getNextEvent(PollEvent *e){	if(mCurResult == mNumResults)		return EWOULDBLOCK;	// no more events	struct kevent *ke = &mResults[mCurResult++];	memset(e, 0, sizeof(struct PollEvent));	e->fd = ke->ident;	if (ke->filter == EVFILT_READ)		e->revents = POLLIN;	else if (ke->filter == EVFILT_WRITE)		e->revents = POLLOUT;	else		e->revents = POLLERR;	// huh, what's this?	e->client = (Client*)ke->udata;	return 0;}int Poller_kqueue::waitAndDispatchEvents(int timeout_millisec){	struct PollEvent pe;	if(waitForEvents(timeout_millisec))		return EWOULDBLOCK;	while(getNextEvent(&pe) == 0) {		Client *client = pe.client;		if(client)			client->notifyPollEvent(&pe);	}	return 0;}#endif /* HAVE_KQUEUE */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -