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; }
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; }