Ejemplo n.º 1
0
bool ThreadPoolWorker::ThreadFunction(void *port)
{
#if defined(CAT_OS_WINDOWS)

	DWORD bytes;
	void *key = 0;
	AsyncBuffer *buffer = 0;
	int error;

	// Initialize ThreadPool Local Storage (CSPRNG, math library)
	ThreadPoolLocalStorage tls;

	if (!tls.Valid())
	{
		FATAL("ThreadPool") << "Unable to initialize thread local storage objects";

		return false;
	}

	for (;;)
	{
		error = GetQueuedCompletionStatus((HANDLE)port, &bytes,
			(PULONG_PTR)&key, (OVERLAPPED**)&buffer, INFINITE)
			? 0 : GetLastError();

		// Terminate thread when we receive a zeroed completion packet
		if (!bytes && !key && !buffer)
			return true;

		// If completion object is NOT specified,
		ThreadRefObject *obj = reinterpret_cast<ThreadRefObject*>( key );
		if (!obj)
		{
			// Release memory for overlapped object
			buffer->Release();
		}
		else
		{
			// If completion object callback returns TRUE,
			if (buffer->Call(&tls, error, buffer, bytes))
			{
				// Release memory for overlapped object
				buffer->Release();
			}

			// Release reference held on completion object
			obj->ReleaseRef();
		}
	}

#else // CAT_OS_WINDOWS
#error TODO
#endif // CAT_OS_WINDOWS

	return true;
}
Ejemplo n.º 2
0
bool ThreadPoolWorker::ThreadFunction(void *port)
{
#if defined(CAT_OS_WINDOWS)

	DWORD bytes;
	void *key = 0;
	AsyncBuffer *buffer = 0;
	int error;

	// Initialize ThreadPool Local Storage (CSPRNG, math library)
	ThreadPoolLocalStorage tls;

	if (!tls.Valid())
	{
		FATAL("ThreadPool") << "Unable to initialize thread local storage objects";

		return false;
	}

	for (;;)
	{
		error = GetQueuedCompletionStatus((HANDLE)port, &bytes,
			(PULONG_PTR)&key, (OVERLAPPED**)&buffer, INFINITE)
			? 0 : GetLastError();

		// Terminate thread when we receive a zeroed completion packet
		if (!bytes && !key && !buffer)
			return true;

		// If completion object is NOT specified,
		ThreadRefObject *obj = reinterpret_cast<ThreadRefObject*>( key );
		if (!obj)
		{
			// Release memory for overlapped object
			buffer->Release();
		}
		else
		{
			// If completion object callback returns TRUE,
			if (buffer->Call(&tls, error, buffer, bytes))
			{
				// Release memory for overlapped object
				buffer->Release();
			}

			// Release reference held on completion object
			obj->ReleaseRef();
		}
	}

#else

	epoll_event ev_buf[EPOLL_QUEUE_LEN];

	for (;;)
	{
		int n;

		for (;;)
		{
			n = epoll_wait(_port, ev_buf, EPOLL_QUEUE_LEN, -1);

			if (!n == -1 && errno == EINTR))
			{
				FATAL("ThreadPool") << "epoll_wait failure";
				break;
			}
		}

		if (!n)
		{
			FATAL("ThreadPool") << "epoll_wait timeout expired";
			continue;
		}

		for (int ii = 0; ii < n; ++ii)
		{
			poll_entry_t *pe = (poll_entry_t*)ev_buf[ii].data.ptr;

			if (pe->fd == INVALID_SOCKET)
				continue;

			if (ev_buf [i].events & (EPOLLERR | EPOLLHUP))
				pe->events->in_event ();

			if (pe->fd == INVALID_SOCKET)
				continue;

			if (ev_buf [i].events & EPOLLOUT)
				pe->events->out_event ();

			if (pe->fd == INVALID_SOCKET)
				continue;

			if (ev_buf [i].events & EPOLLIN)
				pe->events->in_event ();
		}
	}

#endif

	return true;
}