/// The function that does thread work. static void *iothread_worker(void *unused) { UNUSED(unused); struct spawn_request_t req; while (dequeue_spawn_request(&req)) { debug(5, "pthread %p dequeued", this_thread()); // Perform the work req.handler(); // If there's a completion handler, we have to enqueue it on the result queue. // Note we're using std::function's weirdo operator== here if (req.completion != nullptr) { // Enqueue the result, and tell the main thread about it. enqueue_thread_result(std::move(req)); const char wakeup_byte = IO_SERVICE_RESULT_QUEUE; assert_with_errno(write_loop(s_write_pipe, &wakeup_byte, sizeof wakeup_byte) != -1); } } // We believe we have exhausted the thread request queue. We want to decrement // thread_count and exit. But it's possible that a request just came in. Furthermore, // it's possible that the main thread saw that thread_count is full, and decided to not // spawn a new thread, trusting in one of the existing threads to handle it. But we've already // committed to not handling anything else. Therefore, we have to decrement // the thread count under the lock, which we still hold. Likewise, the main thread must // check the value under the lock. int new_thread_count = --s_spawn_requests.acquire().value.thread_count; assert(new_thread_count >= 0); debug(5, "pthread %p exiting", this_thread()); // We're done. return NULL; }
/// The function that does thread work. static void *iothread_worker(void *unused) { scoped_lock locker(s_spawn_queue_lock); struct SpawnRequest_t *req; while ((req = dequeue_spawn_request()) != NULL) { IOTHREAD_LOG fprintf(stderr, "pthread %p dequeued %p\n", this_thread(), req); // Unlock the queue while we execute the request. locker.unlock(); // Perform the work. req->handlerResult = req->handler(req->context); // If there's a completion handler, we have to enqueue it on the result queue. Otherwise, we // can just delete the request! if (req->completionCallback == NULL) { delete req; } else { // Enqueue the result, and tell the main thread about it. enqueue_thread_result(req); const char wakeup_byte = IO_SERVICE_RESULT_QUEUE; VOMIT_ON_FAILURE(!write_loop(s_write_pipe, &wakeup_byte, sizeof wakeup_byte)); } // Lock us up again. locker.lock(); } // We believe we have exhausted the thread request queue. We want to decrement // s_active_thread_count and exit. But it's possible that a request just came in. Furthermore, // it's possible that the main thread saw that s_active_thread_count is full, and decided to not // spawn a new thread, trusting in one of the existing threads to handle it. But we've already // committed to not handling anything else. Therefore, we have to decrement // s_active_thread_count under the lock, which we still hold. Likewise, the main thread must // check the value under the lock. ASSERT_IS_LOCKED(s_spawn_queue_lock); assert(s_active_thread_count > 0); s_active_thread_count -= 1; IOTHREAD_LOG fprintf(stderr, "pthread %p exiting\n", this_thread()); // We're done. return NULL; }
connection::~connection(void) { LOG_TRACE_ALL("destruct a connection resource ok, thread id:%u\n", this_thread()); }