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;
}
nsresult
nsSocketTransportService::DetachSocket(SocketContext *sock)
{
    LOG(("nsSocketTransportService::DetachSocket [handler=%x]\n", sock->mHandler));

    // inform the handler that this socket is going away
    sock->mHandler->OnSocketDetached(sock->mFD);

    // cleanup
    sock->mFD = nsnull;
    NS_RELEASE(sock->mHandler);

    // find out what list this is on.
    PRUint32 index = sock - mActiveList;
    if (index < NS_SOCKET_MAX_COUNT)
        RemoveFromPollList(sock);
    else
        RemoveFromIdleList(sock);

    // NOTE: sock is now an invalid pointer
    
    //
    // notify the first element on the pending socket queue...
    //
    if (!PR_CLIST_IS_EMPTY(&mPendingSocketQ)) {
        // move event from pending queue to event queue
        PLEvent *event = PLEVENT_FROM_LINK(PR_LIST_HEAD(&mPendingSocketQ));
        PR_REMOVE_AND_INIT_LINK(&event->link);
        PostEvent(event);
    }
    return NS_OK;
}
Пример #3
0
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"));
}