int SocketEngine::DispatchEvents()
{
	timeval tval;
	tval.tv_sec = 1;
	tval.tv_usec = 0;

	fd_set rfdset = ReadSet, wfdset = WriteSet, errfdset = ErrSet;

	int sresult = select(MaxFD + 1, &rfdset, &wfdset, &errfdset, &tval);
	ServerInstance->UpdateTime();

	for (int i = 0, j = sresult; i <= MaxFD && j > 0; i++)
	{
		int has_read = FD_ISSET(i, &rfdset), has_write = FD_ISSET(i, &wfdset), has_error = FD_ISSET(i, &errfdset);

		if (!(has_read || has_write || has_error))
			continue;

		--j;

		EventHandler* ev = GetRef(i);
		if (!ev)
			continue;

		if (has_error)
		{
			stats.ErrorEvents++;

			socklen_t codesize = sizeof(int);
			int errcode = 0;
			if (getsockopt(i, SOL_SOCKET, SO_ERROR, (char*)&errcode, &codesize) < 0)
				errcode = errno;

			ev->HandleEvent(EVENT_ERROR, errcode);
			continue;
		}

		if (has_read)
		{
			stats.ReadEvents++;
			ev->SetEventMask(ev->GetEventMask() & ~FD_READ_WILL_BLOCK);
			ev->HandleEvent(EVENT_READ);
			if (ev != GetRef(i))
				continue;
		}

		if (has_write)
		{
			stats.WriteEvents++;
			int newmask = (ev->GetEventMask() & ~(FD_WRITE_WILL_BLOCK | FD_WANT_SINGLE_WRITE));
			SocketEngine::OnSetEvent(ev, ev->GetEventMask(), newmask);
			ev->SetEventMask(newmask);
			ev->HandleEvent(EVENT_WRITE);
		}
	}

	return sresult;
}
Пример #2
0
int SocketEngine::DispatchEvents()
{
	int i = poll(&events[0], CurrentSetSize, 1000);
	int processed = 0;
	ServerInstance->UpdateTime();

	for (int index = 0; index < CurrentSetSize && processed < i; index++)
	{
		struct pollfd& pfd = events[index];

		// Copy these in case the vector gets resized and pfd invalidated
		const int fd = pfd.fd;
		const short revents = pfd.revents;

		if (revents)
			processed++;

		EventHandler* eh = GetRef(fd);
		if (!eh)
			continue;

		if (revents & POLLHUP)
		{
			eh->HandleEvent(EVENT_ERROR, 0);
			continue;
		}

		if (revents & POLLERR)
		{
			// Get error number
			socklen_t codesize = sizeof(int);
			int errcode;
			if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &errcode, &codesize) < 0)
				errcode = errno;
			eh->HandleEvent(EVENT_ERROR, errcode);
			continue;
		}

		if (revents & POLLIN)
		{
			eh->SetEventMask(eh->GetEventMask() & ~FD_READ_WILL_BLOCK);
			eh->HandleEvent(EVENT_READ);
			if (eh != GetRef(fd))
				// whoops, deleted out from under us
				continue;
		}

		if (revents & POLLOUT)
		{
			int mask = eh->GetEventMask();
			mask &= ~(FD_WRITE_WILL_BLOCK | FD_WANT_SINGLE_WRITE);
			eh->SetEventMask(mask);

			// The vector could've been resized, reference can be invalid by now; don't use it
			events[index].events = mask_to_poll(mask);
			eh->HandleEvent(EVENT_WRITE);
		}
	}

	return i;
}