diff options
Diffstat (limited to 'indra/llcommon')
-rw-r--r-- | indra/llcommon/llapr.cpp | 161 | ||||
-rw-r--r-- | indra/llcommon/llapr.h | 34 | ||||
-rw-r--r-- | indra/llcommon/llqueuedthread.cpp | 70 | ||||
-rw-r--r-- | indra/llcommon/llqueuedthread.h | 4 | ||||
-rw-r--r-- | indra/llcommon/llthread.h | 2 | ||||
-rw-r--r-- | indra/llcommon/llworkerthread.cpp | 1 | ||||
-rw-r--r-- | indra/llcommon/llworkerthread.h | 6 |
7 files changed, 184 insertions, 94 deletions
diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp index 669afc5330..ed70b1d9f2 100644 --- a/indra/llcommon/llapr.cpp +++ b/indra/llcommon/llapr.cpp @@ -57,7 +57,7 @@ void ll_init_apr() if(!LLAPRFile::sAPRFilePoolp) { - LLAPRFile::sAPRFilePoolp = new LLVolatileAPRPool() ; + LLAPRFile::sAPRFilePoolp = new LLVolatileAPRPool(FALSE) ; } } @@ -99,13 +99,12 @@ void ll_cleanup_apr() // //LLAPRPool // -LLAPRPool::LLAPRPool(apr_pool_t *parent, apr_size_t size, BOOL releasePoolFlag) -{ - mParent = parent ; - mReleasePoolFlag = releasePoolFlag ; - mMaxSize = size ; - mPool = NULL ; - +LLAPRPool::LLAPRPool(apr_pool_t *parent, apr_size_t size, BOOL releasePoolFlag) + : mParent(parent), + mReleasePoolFlag(releasePoolFlag), + mMaxSize(size), + mPool(NULL) +{ createAPRPool() ; } @@ -148,31 +147,65 @@ void LLAPRPool::releaseAPRPool() } } +//virtual apr_pool_t* LLAPRPool::getAPRPool() +{ + return mPool ; +} + +LLVolatileAPRPool::LLVolatileAPRPool(BOOL is_local, apr_pool_t *parent, apr_size_t size, BOOL releasePoolFlag) + : LLAPRPool(parent, size, releasePoolFlag), + mNumActiveRef(0), + mNumTotalRef(0), + mMutexPool(NULL), + mMutexp(NULL) { - if(!mPool) + //create mutex + if(!is_local) //not a local apr_pool, that is: shared by multiple threads. { - createAPRPool() ; + apr_pool_create(&mMutexPool, NULL); // Create a pool for mutex + apr_thread_mutex_create(&mMutexp, APR_THREAD_MUTEX_UNNESTED, mMutexPool); } - - return mPool ; } -LLVolatileAPRPool::LLVolatileAPRPool(apr_pool_t *parent, apr_size_t size, BOOL releasePoolFlag) - : LLAPRPool(parent, size, releasePoolFlag) + +LLVolatileAPRPool::~LLVolatileAPRPool() { - mNumActiveRef = 0 ; - mNumTotalRef = 0 ; + //delete mutex + if(mMutexp) + { + apr_thread_mutex_destroy(mMutexp); + apr_pool_destroy(mMutexPool); + } } -apr_pool_t* LLVolatileAPRPool::getVolatileAPRPool() +// +//define this virtual function to avoid any mistakenly calling LLAPRPool::getAPRPool(). +// +//virtual +apr_pool_t* LLVolatileAPRPool::getAPRPool() { + return LLVolatileAPRPool::getVolatileAPRPool() ; +} + +apr_pool_t* LLVolatileAPRPool::getVolatileAPRPool() +{ + LLScopedLock lock(mMutexp) ; + mNumTotalRef++ ; mNumActiveRef++ ; - return getAPRPool() ; + + if(!mPool) + { + createAPRPool() ; + } + + return mPool ; } void LLVolatileAPRPool::clearVolatileAPRPool() { + LLScopedLock lock(mMutexp) ; + if(mNumActiveRef > 0) { mNumActiveRef--; @@ -251,10 +284,9 @@ void LLScopedLock::unlock() bool ll_apr_warn_status(apr_status_t status) { if(APR_SUCCESS == status) return false; -#ifndef LL_WINDOWS char buf[MAX_STRING]; /* Flawfinder: ignore */ - LL_WARNS_ONCE("APR") << "APR: " << apr_strerror(status, buf, MAX_STRING) << LL_ENDL; -#endif + apr_strerror(status, buf, MAX_STRING); + LL_WARNS("APR") << "APR: " << buf << LL_ENDL; return true; } @@ -268,10 +300,18 @@ void ll_apr_assert_status(apr_status_t status) // LLAPRFile functions // LLAPRFile::LLAPRFile() + : mFile(NULL), + mCurrentFilePoolp(NULL) +{ +} + +LLAPRFile::LLAPRFile(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool) + : mFile(NULL), + mCurrentFilePoolp(NULL) { - mFile = NULL ; - mCurrentFilePoolp = NULL ; + open(filename, flags, pool); } + LLAPRFile::~LLAPRFile() { close() ; @@ -295,11 +335,40 @@ apr_status_t LLAPRFile::close() return ret ; } -apr_status_t LLAPRFile::open(LLVolatileAPRPool* pool, const std::string& filename, apr_int32_t flags, S32* sizep) +apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool, S32* sizep) { apr_status_t s ; - s = open(filename, flags, pool ? pool->getVolatileAPRPool() : NULL, sizep) ; + + //check if already open some file + llassert_always(!mFile) ; + llassert_always(!mCurrentFilePoolp) ; + apr_pool_t* apr_pool = pool ? pool->getVolatileAPRPool() : NULL ; + s = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, getAPRFilePool(apr_pool)); + + if (s != APR_SUCCESS || !mFile) + { + mFile = NULL ; + + if (sizep) + { + *sizep = 0; + } + } + else if (sizep) + { + S32 file_size = 0; + apr_off_t offset = 0; + if (apr_file_seek(mFile, APR_END, &offset) == APR_SUCCESS) + { + llassert_always(offset <= 0x7fffffff); + file_size = (S32)offset; + offset = 0; + apr_file_seek(mFile, APR_SET, &offset); + } + *sizep = file_size; + } + if(!mCurrentFilePoolp) { mCurrentFilePoolp = pool ; @@ -312,40 +381,25 @@ apr_status_t LLAPRFile::open(LLVolatileAPRPool* pool, const std::string& filenam return s ; } -apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, apr_pool_t* pool, S32* sizep) + +//use gAPRPoolp. +apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, BOOL use_global_pool) { apr_status_t s; //check if already open some file llassert_always(!mFile) ; llassert_always(!mCurrentFilePoolp) ; + llassert_always(use_global_pool) ; //be aware of using gAPRPoolp. - s = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, getAPRFilePool(pool)); + s = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, gAPRPoolp); if (s != APR_SUCCESS || !mFile) { mFile = NULL ; close() ; - if (sizep) - { - *sizep = 0; - } return s; } - if (sizep) - { - S32 file_size = 0; - apr_off_t offset = 0; - if (apr_file_seek(mFile, APR_END, &offset) == APR_SUCCESS) - { - llassert_always(offset <= 0x7fffffff); - file_size = (S32)offset; - offset = 0; - apr_file_seek(mFile, APR_SET, &offset); - } - *sizep = file_size; - } - return s; } @@ -369,6 +423,7 @@ S32 LLAPRFile::read(void *buf, S32 nbytes) apr_status_t s = apr_file_read(mFile, buf, &sz); if (s != APR_SUCCESS) { + ll_apr_warn_status(s); return 0; } else @@ -386,6 +441,7 @@ S32 LLAPRFile::write(const void *buf, S32 nbytes) apr_status_t s = apr_file_write(mFile, buf, &sz); if (s != APR_SUCCESS) { + ll_apr_warn_status(s); return 0; } else @@ -434,6 +490,8 @@ apr_file_t* LLAPRFile::open(const std::string& filename, LLVolatileAPRPool* pool s = apr_file_open(&file_handle, filename.c_str(), flags, APR_OS_DEFAULT, pool->getVolatileAPRPool()); if (s != APR_SUCCESS || !file_handle) { + ll_apr_warn_status(s); + LL_WARNS("APR") << " Attempting to open filename: " << filename << LL_ENDL; file_handle = NULL ; close(file_handle, pool) ; return NULL; @@ -464,6 +522,7 @@ S32 LLAPRFile::seek(apr_file_t* file_handle, apr_seek_where_t where, S32 offset) } if (s != APR_SUCCESS) { + ll_apr_warn_status(s); return -1; } else @@ -501,6 +560,8 @@ S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nb apr_status_t s = apr_file_read(file_handle, buf, &bytes_read); if (s != APR_SUCCESS) { + LL_WARNS("APR") << " Attempting to read filename: " << filename << LL_ENDL; + ll_apr_warn_status(s); bytes_read = 0; } else @@ -549,6 +610,8 @@ S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 n apr_status_t s = apr_file_write(file_handle, buf, &bytes_written); if (s != APR_SUCCESS) { + LL_WARNS("APR") << " Attempting to write filename: " << filename << LL_ENDL; + ll_apr_warn_status(s); bytes_written = 0; } else @@ -575,8 +638,8 @@ bool LLAPRFile::remove(const std::string& filename, LLVolatileAPRPool* pool) if (s != APR_SUCCESS) { - LL_DEBUGS("APR") << "LLAPRFile::remove failed on file: " << filename << LL_ENDL; ll_apr_warn_status(s); + LL_WARNS("APR") << " Attempting to remove filename: " << filename << LL_ENDL; return false; } return true; @@ -593,8 +656,8 @@ bool LLAPRFile::rename(const std::string& filename, const std::string& newname, if (s != APR_SUCCESS) { - LL_DEBUGS("APR") << "LLAPRFile::rename failed on file: " << filename << LL_ENDL; ll_apr_warn_status(s); + LL_WARNS("APR") << " Attempting to rename filename: " << filename << LL_ENDL; return false; } return true; @@ -667,8 +730,8 @@ bool LLAPRFile::makeDir(const std::string& dirname, LLVolatileAPRPool* pool) if (s != APR_SUCCESS) { - LL_DEBUGS("APR") << "LLAPRFile::makeDir failed on file: " << dirname << LL_ENDL; ll_apr_warn_status(s); + LL_WARNS("APR") << " Attempting to make directory: " << dirname << LL_ENDL; return false; } return true; @@ -685,8 +748,8 @@ bool LLAPRFile::removeDir(const std::string& dirname, LLVolatileAPRPool* pool) if (s != APR_SUCCESS) { - LL_DEBUGS("APR") << "LLAPRFile::removeDir failed on file: " << dirname << LL_ENDL; ll_apr_warn_status(s); + LL_WARNS("APR") << " Attempting to remove directory: " << dirname << LL_ENDL; return false; } return true; diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h index 63130a89fc..a1a4c6db4a 100644 --- a/indra/llcommon/llapr.h +++ b/indra/llcommon/llapr.h @@ -70,9 +70,9 @@ class LLAPRPool { public: LLAPRPool(apr_pool_t *parent = NULL, apr_size_t size = 0, BOOL releasePoolFlag = TRUE) ; - ~LLAPRPool() ; + virtual ~LLAPRPool() ; - apr_pool_t* getAPRPool() ; + virtual apr_pool_t* getAPRPool() ; apr_status_t getStatus() {return mStatus ; } protected: @@ -95,18 +95,21 @@ protected: class LLVolatileAPRPool : public LLAPRPool { public: - LLVolatileAPRPool(apr_pool_t *parent = NULL, apr_size_t size = 0, BOOL releasePoolFlag = TRUE); - ~LLVolatileAPRPool(){} + LLVolatileAPRPool(BOOL is_local = TRUE, apr_pool_t *parent = NULL, apr_size_t size = 0, BOOL releasePoolFlag = TRUE); + virtual ~LLVolatileAPRPool(); - apr_pool_t* getVolatileAPRPool() ; - + /*virtual*/ apr_pool_t* getAPRPool() ; //define this virtual function to avoid any mistakenly calling LLAPRPool::getAPRPool(). + apr_pool_t* getVolatileAPRPool() ; void clearVolatileAPRPool() ; BOOL isFull() ; - BOOL isEmpty() {return !mNumActiveRef ;} + private: S32 mNumActiveRef ; //number of active pointers pointing to the apr_pool. - S32 mNumTotalRef ; //number of total pointers pointing to the apr_pool since last creating. + S32 mNumTotalRef ; //number of total pointers pointing to the apr_pool since last creating. + + apr_thread_mutex_t *mMutexp; + apr_pool_t *mMutexPool; } ; /** @@ -192,18 +195,21 @@ typedef LLAtomic32<S32> LLAtomicS32; // 1, a temperary pool passed to an APRFile function, which is used within this function and only once. // 2, a global pool. // -class LLAPRFile + +class LLAPRFile : boost::noncopyable { + // make this non copyable since a copy closes the file private: apr_file_t* mFile ; LLVolatileAPRPool *mCurrentFilePoolp ; //currently in use apr_pool, could be one of them: sAPRFilePoolp, or a temp pool. public: LLAPRFile() ; + LLAPRFile(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool = NULL); ~LLAPRFile() ; - - apr_status_t open(LLVolatileAPRPool* pool, const std::string& filename, apr_int32_t flags, S32* sizep = NULL); - apr_status_t open(const std::string& filename, apr_int32_t flags, apr_pool_t* pool = NULL, S32* sizep = NULL); + + apr_status_t open(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool = NULL, S32* sizep = NULL); + apr_status_t open(const std::string& filename, apr_int32_t flags, BOOL use_global_pool); //use gAPRPoolp. apr_status_t close() ; // Returns actual offset, -1 if seek fails @@ -217,8 +223,8 @@ public: apr_file_t* getFileHandle() {return mFile;} private: - apr_pool_t* getAPRFilePool(apr_pool_t* pool) ; - + apr_pool_t* getAPRFilePool(apr_pool_t* pool) ; + // //******************************************************************************************************************************* //static components diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp index 3db5c36545..395d298887 100644 --- a/indra/llcommon/llqueuedthread.cpp +++ b/indra/llcommon/llqueuedthread.cpp @@ -42,7 +42,8 @@ LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded) : LLThread(name), mThreaded(threaded), mIdleThread(TRUE), - mNextHandle(0) + mNextHandle(0), + mStarted(FALSE) { if (mThreaded) { @@ -53,6 +54,10 @@ LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded) : // MAIN THREAD LLQueuedThread::~LLQueuedThread() { + if (!mThreaded) + { + endThread(); + } shutdown(); // ~LLThread() will be called here } @@ -106,6 +111,11 @@ void LLQueuedThread::shutdown() // virtual S32 LLQueuedThread::update(U32 max_time_ms) { + if (!mStarted) + { + startThread(); + mStarted = TRUE; + } return updateQueue(max_time_ms); } @@ -452,26 +462,12 @@ S32 LLQueuedThread::processNextRequest() } } - S32 res; S32 pending = getPending(); - if (pending == 0) - { - if (isQuitting()) - { - res = -1; // exit thread - } - else - { - res = 0; - } - } - else - { - res = pending; - } - return res; + + return pending; } +// virtual bool LLQueuedThread::runCondition() { // mRunCondition must be locked here @@ -481,35 +477,53 @@ bool LLQueuedThread::runCondition() return true; } +// virtual void LLQueuedThread::run() { + // call checPause() immediately so we don't try to do anything before the class is fully constructed + checkPause(); + startThread(); + mStarted = TRUE; + while (1) { // this will block on the condition until runCondition() returns true, the thread is unpaused, or the thread leaves the RUNNING state. checkPause(); - if(isQuitting()) + if (isQuitting()) + { + endThread(); break; - - //llinfos << "QUEUED THREAD RUNNING, queue size = " << mRequestQueue.size() << llendl; + } mIdleThread = FALSE; + + threadedUpdate(); int res = processNextRequest(); if (res == 0) { mIdleThread = TRUE; + ms_sleep(1); } - - if (res < 0) // finished working and want to exit - { - break; - } - //LLThread::yield(); // thread should yield after each request } + llinfos << "LLQueuedThread " << mName << " EXITING." << llendl; +} - llinfos << "QUEUED THREAD " << mName << " EXITING." << llendl; +// virtual +void LLQueuedThread::startThread() +{ +} + +// virtual +void LLQueuedThread::endThread() +{ +} + +// virtual +void LLQueuedThread::threadedUpdate() +{ } //============================================================================ diff --git a/indra/llcommon/llqueuedthread.h b/indra/llcommon/llqueuedthread.h index 3ba43e1e07..bcd154da0b 100644 --- a/indra/llcommon/llqueuedthread.h +++ b/indra/llcommon/llqueuedthread.h @@ -165,6 +165,9 @@ private: virtual bool runCondition(void); virtual void run(void); + virtual void startThread(void); + virtual void endThread(void); + virtual void threadedUpdate(void); protected: handle_t generateHandle(); @@ -199,6 +202,7 @@ public: protected: BOOL mThreaded; // if false, run on main thread and do updates during update() + BOOL mStarted; // required when mThreaded is false to call startThread() from update() LLAtomic32<BOOL> mIdleThread; // request queue is empty (or we are quitting) and the thread is idle typedef std::set<QueuedRequest*, queued_request_less> request_queue_t; diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h index f25339f48d..1470dca14c 100644 --- a/indra/llcommon/llthread.h +++ b/indra/llcommon/llthread.h @@ -33,9 +33,7 @@ #ifndef LL_LLTHREAD_H #define LL_LLTHREAD_H -#include "llapr.h" #include "llapp.h" - #include "apr_thread_cond.h" class LLThread; diff --git a/indra/llcommon/llworkerthread.cpp b/indra/llcommon/llworkerthread.cpp index 5dda600755..82c736266d 100644 --- a/indra/llcommon/llworkerthread.cpp +++ b/indra/llcommon/llworkerthread.cpp @@ -201,6 +201,7 @@ LLWorkerClass::~LLWorkerClass() { llassert_always(!(mWorkFlags & WCF_WORKING)); llassert_always(mWorkFlags & WCF_DELETE_REQUESTED); + llassert_always(!mMutex.isLocked()); if (mRequestHandle != LLWorkerThread::nullHandle()) { LLWorkerThread::WorkRequest* workreq = (LLWorkerThread::WorkRequest*)mWorkerThread->getRequest(mRequestHandle); diff --git a/indra/llcommon/llworkerthread.h b/indra/llcommon/llworkerthread.h index 19407f4463..4a4cd6c85f 100644 --- a/indra/llcommon/llworkerthread.h +++ b/indra/llcommon/llworkerthread.h @@ -52,6 +52,7 @@ class LLWorkerClass; class LLWorkerThread : public LLQueuedThread { + friend class LLWorkerClass; public: class WorkRequest : public LLQueuedThread::QueuedRequest { @@ -92,8 +93,11 @@ public: handle_t addWorkRequest(LLWorkerClass* workerclass, S32 param, U32 priority = PRIORITY_NORMAL); - void deleteWorker(LLWorkerClass* workerclass); // schedule for deletion S32 getNumDeletes() { return (S32)mDeleteList.size(); } // debug + +private: + void deleteWorker(LLWorkerClass* workerclass); // schedule for deletion + }; //============================================================================ |