PRBool nsSocketTransportService::ServiceEventQ() { PRBool keepGoing; // grab the event queue PRCList eq; PR_INIT_CLIST(&eq); { nsAutoLock lock(mEventQLock); MoveCList(mEventQ, eq); // check to see if we're supposed to shutdown keepGoing = mInitialized; } // service the event queue PLEvent *event; while (!PR_CLIST_IS_EMPTY(&eq)) { event = PLEVENT_FROM_LINK(PR_LIST_HEAD(&eq)); PR_REMOVE_AND_INIT_LINK(&event->link); PL_HandleEvent(event); } return keepGoing; }
void nsIOThreadPool::ThreadFunc(void *arg) { nsIOThreadPool *pool = (nsIOThreadPool *) arg; LOG(("entering ThreadFunc\n")); { nsAutoLock lock(pool->mLock); for (;;) { PRIntervalTime start = PR_IntervalNow(), timeout = IDLE_TIMEOUT; // // wait for one or more of the following to occur: // (1) the event queue has an event to process // (2) the shutdown flag has been set // (3) the thread has been idle for too long // // PR_WaitCondVar will return when any of these conditions is true. // while (PR_CLIST_IS_EMPTY(&pool->mEventQ) && !pool->mShutdown) { pool->mNumIdleThreads++; PR_WaitCondVar(pool->mIdleThreadCV, timeout); pool->mNumIdleThreads--; PRIntervalTime delta = PR_IntervalNow() - start; if (delta >= timeout) break; timeout -= delta; start += delta; } // if the queue is still empty, then kill this thread (either we // are shutting down or the thread exceeded the idle timeout)... if (PR_CLIST_IS_EMPTY(&pool->mEventQ)) break; // handle one event at a time: we don't want this one thread to hog // all the events while other threads may be able to help out ;-) do { PLEvent *event = PLEVENT_FROM_LINK(PR_LIST_HEAD(&pool->mEventQ)); PR_REMOVE_AND_INIT_LINK(&event->link); LOG(("event:%p\n", event)); // release lock! lock.unlock(); PL_HandleEvent(event); lock.lock(); } while (!PR_CLIST_IS_EMPTY(&pool->mEventQ)); } // thread is going away... pool->mNumThreads--; PR_NotifyCondVar(pool->mExitThreadCV); } // release our reference to the pool NS_RELEASE(pool); LOG(("leaving ThreadFunc\n")); }