static void delete_threadpool(PRThreadPool *tp) { if (NULL != tp) { if (NULL != tp->shutdown_cv) PR_DestroyCondVar(tp->shutdown_cv); if (NULL != tp->jobq.cv) PR_DestroyCondVar(tp->jobq.cv); if (NULL != tp->jobq.lock) PR_DestroyLock(tp->jobq.lock); if (NULL != tp->join_lock) PR_DestroyLock(tp->join_lock); #ifdef OPT_WINNT if (NULL != tp->jobq.nt_completion_port) CloseHandle(tp->jobq.nt_completion_port); #endif /* Timer queue */ if (NULL != tp->timerq.cv) PR_DestroyCondVar(tp->timerq.cv); if (NULL != tp->timerq.lock) PR_DestroyLock(tp->timerq.lock); if (NULL != tp->ioq.lock) PR_DestroyLock(tp->ioq.lock); if (NULL != tp->ioq.pollfds) PR_Free(tp->ioq.pollfds); if (NULL != tp->ioq.notify_fd) PR_DestroyPollableEvent(tp->ioq.notify_fd); PR_Free(tp); } return; }
nsSocketTransportService::~nsSocketTransportService() { NS_ASSERTION(nsIThread::IsMainThread(), "wrong thread"); NS_ASSERTION(!mInitialized, "not shutdown properly"); PR_DestroyLock(mEventQLock); if (mThreadEvent) PR_DestroyPollableEvent(mThreadEvent); gSocketTransportService = nsnull; }
static void ConnDestroy(ipcConnectionState *s) { if (s->lock) PR_DestroyLock(s->lock); if (s->fds[SOCK].fd) PR_Close(s->fds[SOCK].fd); if (s->fds[POLL].fd) PR_DestroyPollableEvent(s->fds[POLL].fd); if (s->in_msg) delete s->in_msg; s->send_queue.DeleteAll(); delete s; }
NS_IMETHODIMP nsSocketTransportService::Run() { LOG(("nsSocketTransportService::Run")); gSocketThread = PR_GetCurrentThread(); // // add thread event to poll list (mThreadEvent may be NULL) // mPollList[0].fd = mThreadEvent; mPollList[0].in_flags = PR_POLL_READ; mPollList[0].out_flags = 0; PRInt32 i, count; // // poll loop // PRBool active = PR_TRUE; while (active) { // // walk active list backwards to see if any sockets should actually be // idle, then walk the idle list backwards to see if any idle sockets // should become active. take care to check only idle sockets that // were idle to begin with ;-) // count = mIdleCount; for (i=mActiveCount-1; i>=0; --i) { //--- LOG((" active [%u] { handler=%x condition=%x pollflags=%hu }\n", i, mActiveList[i].mHandler, mActiveList[i].mHandler->mCondition, mActiveList[i].mHandler->mPollFlags)); //--- if (NS_FAILED(mActiveList[i].mHandler->mCondition)) DetachSocket(&mActiveList[i]); else { PRUint16 in_flags = mActiveList[i].mHandler->mPollFlags; if (in_flags == 0) MoveToIdleList(&mActiveList[i]); else { // update poll flags mPollList[i+1].in_flags = in_flags; mPollList[i+1].out_flags = 0; } } } for (i=count-1; i>=0; --i) { //--- LOG((" idle [%u] { handler=%x condition=%x pollflags=%hu }\n", i, mIdleList[i].mHandler, mIdleList[i].mHandler->mCondition, mIdleList[i].mHandler->mPollFlags)); //--- if (NS_FAILED(mIdleList[i].mHandler->mCondition)) DetachSocket(&mIdleList[i]); else if (mIdleList[i].mHandler->mPollFlags != 0) MoveToPollList(&mIdleList[i]); } LOG((" calling PR_Poll [active=%u idle=%u]\n", mActiveCount, mIdleCount)); // Measures seconds spent while blocked on PR_Poll PRUint32 pollInterval; PRInt32 n = Poll(&pollInterval); if (n < 0) { LOG((" PR_Poll error [%d]\n", PR_GetError())); active = PR_FALSE; } else { // // service "active" sockets... // for (i=0; i<PRInt32(mActiveCount); ++i) { PRPollDesc &desc = mPollList[i+1]; SocketContext &s = mActiveList[i]; if (n > 0 && desc.out_flags != 0) { s.mElapsedTime = 0; s.mHandler->OnSocketReady(desc.fd, desc.out_flags); } // check for timeout errors unless disabled... else if (s.mHandler->mPollTimeout != PR_UINT16_MAX) { // update elapsed time counter if (NS_UNLIKELY(pollInterval > (PR_UINT16_MAX - s.mElapsedTime))) s.mElapsedTime = PR_UINT16_MAX; else s.mElapsedTime += PRUint16(pollInterval); // check for timeout expiration if (s.mElapsedTime >= s.mHandler->mPollTimeout) { s.mElapsedTime = 0; s.mHandler->OnSocketReady(desc.fd, -1); } } } // // check for "dead" sockets and remove them (need to do this in // reverse order obviously). // for (i=mActiveCount-1; i>=0; --i) { if (NS_FAILED(mActiveList[i].mHandler->mCondition)) DetachSocket(&mActiveList[i]); } // // service the event queue (mPollList[0].fd == mThreadEvent) // if (n == 0) active = ServiceEventQ(); else if (mPollList[0].out_flags == PR_POLL_READ) { // acknowledge pollable event (wait should not block) if (PR_WaitForPollableEvent(mThreadEvent) != PR_SUCCESS) { // On Windows, the TCP loopback connection in the // pollable event may become broken when a laptop // switches between wired and wireless networks or // wakes up from hibernation. We try to create a // new pollable event. If that fails, we fall back // on "busy wait". { nsAutoLock lock(mEventQLock); PR_DestroyPollableEvent(mThreadEvent); mThreadEvent = PR_NewPollableEvent(); } if (!mThreadEvent) { NS_WARNING("running socket transport thread without " "a pollable event"); LOG(("running socket transport thread without " "a pollable event")); } mPollList[0].fd = mThreadEvent; // mPollList[0].in_flags was already set to PR_POLL_READ // at the beginning of this method. mPollList[0].out_flags = 0; } active = ServiceEventQ(); } } } // // shutdown thread // LOG(("shutting down socket transport thread...\n")); mShuttingDown = PR_TRUE; // detach any sockets for (i=mActiveCount-1; i>=0; --i) DetachSocket(&mActiveList[i]); for (i=mIdleCount-1; i>=0; --i) DetachSocket(&mIdleList[i]); mShuttingDown = PR_FALSE; // Final pass over the event queue. This makes sure that events posted by // socket detach handlers get processed. ServiceEventQ(); gSocketThread = nsnull; return NS_OK; }