CPDF_Rect CFFL_Utils::MaxRect(const CPDF_Rect & rect1,const CPDF_Rect & rect2) { CPDF_Rect rcRet; rcRet.left = FFL_MIN(rect1.left,rect2.left); rcRet.bottom = FFL_MIN(rect1.bottom,rect2.bottom); rcRet.right = FFL_MAX(rect1.right,rect2.right); rcRet.top = FFL_MAX(rect1.top,rect2.top); return rcRet; }
int Thread::_threadLoop(void* user) { Thread* const self = static_cast<Thread*>(user); sp<Thread> strong(self->mThreadData->mHoldSelf); wp<Thread> weak(strong); self->mThreadData->mHoldSelf.clear(); bool first = true; bool exec_thread_exit = false; {// // 等待run函数返回成功 // CMutex::Autolock _l(self->mThreadData->mLock); if (self->mThreadData->mThread == NULL) { self->mThreadData->mThreadReadyCondition.wait(self->mThreadData->mLock); } } // // 保存一下线程名称 // unsigned long tid=self->mThreadData->mTid = FFL_CurrentThreadID(); char threadName[256] = { 0 }; const char* tmpName = FFL_GetThreadName(self->mThreadData->mThread); if (tmpName != NULL && tmpName[0] != 0) { memcpy(threadName, tmpName, FFL_MIN(strlen(tmpName), 255)); } INTERNAL_FFL_LOG_DEBUG("Thread(%d)(%s) run", tid, threadName); if (self->mThreadData->mPriority != FFL_THREAD_PRIORITY_NORMAL) { FFL_SetThreadPriority(self->mThreadData->mPriority); } self->threadLoopStart(); do { bool result; if (first) { first = false; self->mThreadData->mStatus = self->readyToRun(); result = (self->mThreadData->mStatus == FFL_NO_ERROR); if (result && !self->exitPending()) { // Binder threads (and maybe others) rely on threadLoop // running at least once after a successful ::readyToRun() // (unless, of course, the thread has already been asked to exit // at that point). // This is because threads are essentially used like this: // (new ThreadSubclass())->run(); // The caller therefore does not retain a strong reference to // the thread and the thread would simply disappear after the // successful ::readyToRun() call instead of entering the // threadLoop at least once. result = self->threadLoop(); } } else { result = self->threadLoop(); } // establish a scope for mLock { CMutex::Autolock _l(self->mThreadData->mLock); if (result == false || self->mThreadData->mExitPending) { self->mThreadData->mExitPending = true; self->mThreadData->mRunning = false; // clear thread ID so that requestExitAndWait() does not exit if // called by a new thread using the same thread ID as this one. self->mThreadData->mThread = 0; self->threadLoopExit(self); exec_thread_exit = true; // note that interested observers blocked in requestExitAndWait are // awoken by broadcast, but blocked on mLock until break exits scope self->mThreadData->mThreadExitedCondition.broadcast(); break; } } // Release our strong reference, to let a chance to the thread // to die a peaceful death. strong.clear(); // And immediately, re-acquire a strong reference for the next loop strong = weak.promote(); } while (!strong.is_empty()); if(!exec_thread_exit) self->threadLoopExit(0); INTERNAL_FFL_LOG_DEBUG("Thread(%d)(%s) exit", tid, threadName); return 0; }