From 35e200881c38eb6c1bfd1f14ef440d4bc4da8c74 Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Fri, 6 Nov 2009 06:52:24 +0000
Subject: merge QAR-1829: texture pipeline branch in viewer-2.0.0.3

---
 indra/llcommon/llapr.cpp          | 161 ++++++++++++++++++++++++++------------
 indra/llcommon/llapr.h            |  34 ++++----
 indra/llcommon/llqueuedthread.cpp |  70 ++++++++++-------
 indra/llcommon/llqueuedthread.h   |   4 +
 indra/llcommon/llthread.h         |   2 -
 indra/llcommon/llworkerthread.cpp |   1 +
 indra/llcommon/llworkerthread.h   |   6 +-
 7 files changed, 184 insertions(+), 94 deletions(-)

(limited to 'indra/llcommon')

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
+	
 };
 
 //============================================================================
-- 
cgit v1.2.3