Commits

dessie linden committed 86bd446 Merge

merged .hgtags

Comments (0)

Files changed (530)

 1778f26b6d0ae762dec3ca37140f66620f2485d9 DRTVWR-77_3.0.0-release
 6694f3f062aa45f64ab391d25a3eb3d5eb1b0871 DRTVWR-85_3.0.3-beta1
 6694f3f062aa45f64ab391d25a3eb3d5eb1b0871 3.0.3-beta1
+586907287be581817b2422b5137971b22d54ea48 3.0.4-start
 61aa7974df089e8621fe9a4c69bcdefdb3cc208a DRTVWR-89_3.0.3-beta2
 61aa7974df089e8621fe9a4c69bcdefdb3cc208a 3.0.3-beta2
 0496d2f74043cf4e6058e76ac3db03d44cff42ce DRTVWR-84_3.0.3-release
 0496d2f74043cf4e6058e76ac3db03d44cff42ce 3.0.3-release
+92a3aa04775438226399b19deee12ac3b5a62838 3.0.5-start
+c7282e59f374ee904bd793c3c444455e3399b0c5 3.1.0-start
+2657fa785bbfac115852c41bd0adaff74c2ad5da DRTVWR-93_3.1.0-beta1
+2657fa785bbfac115852c41bd0adaff74c2ad5da 3.1.0-beta1
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>a7c80fd8516df3b879b669b2b220067f</string>
+              <string>1b92a69f5eba7cd8b017180659076db5</string>
               <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llqtwebkit/rev/232420/arch/Darwin/installer/llqtwebkit-4.7.1-darwin-20110608.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/roxie_3p-llqtwebkit/rev/242182/arch/Darwin/installer/llqtwebkit-4.7.1-darwin-20111003.tar.bz2</string>
             </map>
             <key>name</key>
             <string>darwin</string>
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>b9cc0333cc274c9cc40256ab7146b4fc</string>
+              <string>1e7f24b69b0fc751c7e86efe7c621882</string>
               <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llqtwebkit/rev/232420/arch/CYGWIN/installer/llqtwebkit-4.7.1-windows-20110608.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/roxie_3p-llqtwebkit/rev/242182/arch/CYGWIN/installer/llqtwebkit-4.7.1-windows-20111003.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows</string>

doc/contributions.txt

 Alejandro Rosenthal
 	VWR-1184
 Aleric Inglewood
+	SNOW-84
 	SNOW-240
+	SNOW-477
 	SNOW-522
 	SNOW-626
+	SNOW-744
 	SNOW-756
 	SNOW-764
+	SNOW-766
 	SNOW-800
 	VWR-10001
 	VWR-10579
 	VWR-24366
 	VWR-24519
 	VWR-24520
-	SNOW-84
-	SNOW-477
-	SNOW-744
-	SNOW-766
 	STORM-163
+	STORM-864
 	STORM-955
 	STORM-960
 Ales Beaumont
 	VWR-24917
 Argent Stonecutter
 	VWR-68
+ArminWeatherHax
+	STORM-1532
 Armin Weatherwax
 	VWR-8436
 ArminasX Saiman
 Ima Mechanique
 	OPEN-50
 	OPEN-61
+	OPEN-76
 	STORM-1175
 Imnotgoing Sideways
 Inma Rau
 	STORM-1276
 	STORM-1462
 	STORM-1459
+	STORM-1297
+	STORM-1522
+	STORM-1567
+	STORM-1572
+	STORM-1574
 Kadah Coba
     STORM-1060
 Jondan Lundquist

doc/translations.txt

-#List of translators who contribute to SL Viewer 2.0+ and SL web translation by language
+#List of translators who contribute to SL Viewer 2.0+ by language
 
 	Danish
 Flemming Congrejo
+	German
+Torben Trautman
 	French
 Valerie Linden
 	Polish
 Minerva Memel
 Polo Gufler
 Xiki Luik
-Perez Linden
+Shinya Tandino
+Catwise Yoshikawa
 	Traditional Chinese
 gefeit Dufaux

indra/cmake/OpenSSL.cmake

   if (WINDOWS)
     set(OPENSSL_LIBRARIES ssleay32 libeay32)
   else (WINDOWS)
-    set(OPENSSL_LIBRARIES ssl)
+    set(OPENSSL_LIBRARIES ssl crypto)
   endif (WINDOWS)
   set(OPENSSL_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include)
 endif (STANDALONE)

indra/llaudio/llaudioengine_fmod.cpp

 		return false;
 	}
 
-	if (!LLAPRFile::isExist(filename, NULL, LL_APR_RPB))
+	if (!LLAPRFile::isExist(filename, LL_APR_RPB))
 	{
 		// File not found, abort.
 		return false;

indra/llaudio/llvorbisencode.cpp

 	error_msg.clear();
 
 	//********************************
-	LLAPRFile infile ;
-    infile.open(in_fname,LL_APR_RB);
+	LLAPRFile infile(in_fname, LL_APR_RB);
 	//********************************
 	if (!infile.getFileHandle())
 	{
 
 	S32 data_left = 0;
 
-	LLAPRFile infile ;
-	infile.open(in_fname,LL_APR_RB);
+	LLAPRFile infile(in_fname,LL_APR_RB);
 	if (!infile.getFileHandle())
 	{
 		llwarns << "Couldn't open temporary ogg file for writing: " << in_fname
 		return(LLVORBISENC_SOURCE_OPEN_ERR);
 	}
 
-	LLAPRFile outfile ;
-	outfile.open(out_fname,LL_APR_WPB);
+	LLAPRFile outfile(out_fname, LL_APR_WPB);
 	if (!outfile.getFileHandle())
 	{
 		llwarns << "Couldn't open upload sound file for reading: " << in_fname

indra/llcharacter/llbvhloader.cpp

 	//--------------------------------------------------------------------
 	std::string path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,fileName);
 
-	LLAPRFile infile ;
-	infile.open(path, LL_APR_R);
+	LLAPRFile infile(path, LL_APR_R);
 	apr_file_t *fp = infile.getFileHandle();
 	if (!fp)
 		return E_ST_NO_XLT_FILE;

indra/llcharacter/llkeyframemotionparam.cpp

 	// open the file
 	//-------------------------------------------------------------------------
 	S32 fileSize = 0;
-	LLAPRFile infile ;
-	infile.open(path, LL_APR_R, NULL, &fileSize);
+	LLAPRFile infile(path, LL_APR_R, &fileSize);
 	apr_file_t* fp = infile.getFileHandle() ;
 	if (!fp || fileSize == 0)
 	{

indra/llcharacter/llstatemachine.cpp

 
 BOOL LLStateDiagram::saveDotFile(const std::string& filename)
 {
-	LLAPRFile outfile ;
-	outfile.open(filename, LL_APR_W);
+	LLAPRFile outfile(filename, LL_APR_W);
 	apr_file_t* dot_file = outfile.getFileHandle() ;
 
 	if (!dot_file)

indra/llcommon/CMakeLists.txt

     llallocator_heap_profile.cpp
     llapp.cpp
     llapr.cpp
+    llaprpool.cpp
     llassettype.cpp
     llavatarname.cpp
     llbase32.cpp
     llrand.cpp
     llrefcount.cpp
     llrun.cpp
+    llscopedvolatileaprpool.h
     llsd.cpp
     llsdserialize.cpp
     llsdserialize_xml.cpp
     indra_constants.h
     linden_common.h
     linked_lists.h
-    llaccountingquota.h
+    llaccountingcost.h
     llallocator.h
     llallocator_heap_profile.h
     llagentconstants.h
     llavatarname.h
     llapp.h
     llapr.h
+    llaprpool.h
     llassettype.h
     llassoclist.h
     llavatarconstants.h
   LL_ADD_INTEGRATION_TEST(llrand "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llsdserialize "" "${test_libs}"
                           "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/tests/setpython.py")
+  LL_ADD_INTEGRATION_TEST(llsingleton "" "${test_libs}")                          
   LL_ADD_INTEGRATION_TEST(llstring "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(lltreeiterators "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(lluri "" "${test_libs}")

indra/llcommon/llaccountingcost.h

+/** 
+ * @file llaccountingcost.h
+ * @
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_ACCOUNTINGQUOTA_H
+#define LL_ACCOUNTINGQUOTA_H
+
+struct ParcelQuota
+{
+	ParcelQuota( F32 ownerRenderCost,	 F32 ownerPhysicsCost,	  F32 ownerNetworkCost,	   F32 ownerSimulationCost,
+				 F32 groupRenderCost,	 F32 groupPhysicsCost,	  F32 groupNetworkCost,	   F32 groupSimulationCost,
+				 F32 otherRenderCost,	 F32 otherPhysicsCost,	  F32 otherNetworkCost,	   F32 otherSimulationCost,
+				 F32 tempRenderCost,	 F32 tempPhysicsCost,	  F32 tempNetworkCost,	   F32 tempSimulationCost,
+				 F32 selectedRenderCost, F32 selectedPhysicsCost, F32 selectedNetworkCost, F32 selectedSimulationCost,
+				 F32 parcelCapacity )
+	: mOwnerRenderCost( ownerRenderCost ), mOwnerPhysicsCost( ownerPhysicsCost ) 
+	, mOwnerNetworkCost( ownerNetworkCost ), mOwnerSimulationCost( ownerSimulationCost )
+	, mGroupRenderCost( groupRenderCost ), mGroupPhysicsCost( groupPhysicsCost )
+	, mGroupNetworkCost( groupNetworkCost ), mGroupSimulationCost( groupSimulationCost )
+	, mOtherRenderCost( otherRenderCost ), mOtherPhysicsCost( otherPhysicsCost )
+	, mOtherNetworkCost( otherNetworkCost ), mOtherSimulationCost( otherSimulationCost )
+	, mTempRenderCost( tempRenderCost ), mTempPhysicsCost( tempPhysicsCost ) 
+	, mTempNetworkCost( tempNetworkCost ), mTempSimulationCost( tempSimulationCost )
+	, mSelectedRenderCost( tempRenderCost ), mSelectedPhysicsCost( tempPhysicsCost ) 
+	, mSelectedNetworkCost( tempNetworkCost ), mSelectedSimulationCost( selectedSimulationCost )
+	, mParcelCapacity( parcelCapacity )
+	{
+	}
+
+	ParcelQuota(){}			
+	F32 mOwnerRenderCost, mOwnerPhysicsCost, mOwnerNetworkCost, mOwnerSimulationCost;
+	F32 mGroupRenderCost, mGroupPhysicsCost, mGroupNetworkCost, mGroupSimulationCost;
+	F32 mOtherRenderCost, mOtherPhysicsCost, mOtherNetworkCost, mOtherSimulationCost;
+	F32 mTempRenderCost,  mTempPhysicsCost,  mTempNetworkCost,  mTempSimulationCost;
+	F32 mSelectedRenderCost, mSelectedPhysicsCost, mSelectedNetworkCost, mSelectedSimulationCost;
+	F32 mParcelCapacity;
+};
+
+//SelectionQuota atm does not require a id
+struct SelectionCost
+{
+	SelectionCost( /*LLTransactionID transactionId, */ F32 physicsCost, F32 networkCost, F32 simulationCost )
+	//: mTransactionId( transactionId)
+	: mPhysicsCost( physicsCost )
+	, mNetworkCost( networkCost )
+	, mSimulationCost( simulationCost )
+	{
+	}
+	SelectionCost()
+	: mPhysicsCost( 0.0f )
+	, mNetworkCost( 0.0f )
+	, mSimulationCost( 0.0f )
+	{}
+	
+	F32 mPhysicsCost, mNetworkCost, mSimulationCost;	
+	//LLTransactionID mTransactionId;
+};
+
+typedef enum { Roots = 0 , Prims } eSelectionType;
+
+#endif
+
+
+

indra/llcommon/llaccountingquota.h

-/** 
- * @file llaccountingquota.h
- * @
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2011, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_ACCOUNTINGQUOTA_H
-#define LL_ACCOUNTINGQUOTA_H
-
-struct ParcelQuota
-{
-	ParcelQuota( F32 ownerRenderCost,	 F32 ownerPhysicsCost,	  F32 ownerNetworkCost,	   F32 ownerSimulationCost,
-				 F32 groupRenderCost,	 F32 groupPhysicsCost,	  F32 groupNetworkCost,	   F32 groupSimulationCost,
-				 F32 otherRenderCost,	 F32 otherPhysicsCost,	  F32 otherNetworkCost,	   F32 otherSimulationCost,
-				 F32 tempRenderCost,	 F32 tempPhysicsCost,	  F32 tempNetworkCost,	   F32 tempSimulationCost,
-				 F32 selectedRenderCost, F32 selectedPhysicsCost, F32 selectedNetworkCost, F32 selectedSimulationCost,
-				 F32 parcelCapacity )
-	: mOwnerRenderCost( ownerRenderCost ), mOwnerPhysicsCost( ownerPhysicsCost ) 
-	, mOwnerNetworkCost( ownerNetworkCost ), mOwnerSimulationCost( ownerSimulationCost )
-	, mGroupRenderCost( groupRenderCost ), mGroupPhysicsCost( groupPhysicsCost )
-	, mGroupNetworkCost( groupNetworkCost ), mGroupSimulationCost( groupSimulationCost )
-	, mOtherRenderCost( otherRenderCost ), mOtherPhysicsCost( otherPhysicsCost )
-	, mOtherNetworkCost( otherNetworkCost ), mOtherSimulationCost( otherSimulationCost )
-	, mTempRenderCost( tempRenderCost ), mTempPhysicsCost( tempPhysicsCost ) 
-	, mTempNetworkCost( tempNetworkCost ), mTempSimulationCost( tempSimulationCost )
-	, mSelectedRenderCost( tempRenderCost ), mSelectedPhysicsCost( tempPhysicsCost ) 
-	, mSelectedNetworkCost( tempNetworkCost ), mSelectedSimulationCost( selectedSimulationCost )
-	, mParcelCapacity( parcelCapacity )
-	{
-	}
-
-	ParcelQuota(){}			
-	F32 mOwnerRenderCost, mOwnerPhysicsCost, mOwnerNetworkCost, mOwnerSimulationCost;
-	F32 mGroupRenderCost, mGroupPhysicsCost, mGroupNetworkCost, mGroupSimulationCost;
-	F32 mOtherRenderCost, mOtherPhysicsCost, mOtherNetworkCost, mOtherSimulationCost;
-	F32 mTempRenderCost,  mTempPhysicsCost,  mTempNetworkCost,  mTempSimulationCost;
-	F32 mSelectedRenderCost, mSelectedPhysicsCost, mSelectedNetworkCost, mSelectedSimulationCost;
-	F32 mParcelCapacity;
-};
-
-struct SelectionQuota
-{
-	SelectionQuota( LLUUID localId, F32 renderCost, F32 physicsCost, F32 networkCost, F32 simulationCost )
-	: mLocalId( localId)
-	, mRenderCost( renderCost )
-	, mPhysicsCost( physicsCost )
-	, mNetworkCost( networkCost )
-	, mSimulationCost( simulationCost )
-	{
-	}
-	SelectionQuota() {}
-	
-	F32 mRenderCost, mPhysicsCost, mNetworkCost, mSimulationCost;	
-	LLUUID mLocalId;
-};
-
-#endif
-
-
-

indra/llcommon/llapp.cpp

 		mOptions.append(sd);
 	}
 
-	// Make sure we clean up APR when we exit
-	// Don't need to do this if we're cleaning up APR in the destructor
-	//atexit(ll_cleanup_apr);
-
 	// Set the application to this instance.
 	sApplication = this;
 	

indra/llcommon/llapr.cpp

 #include "linden_common.h"
 #include "llapr.h"
 #include "apr_dso.h"
+#include "llscopedvolatileaprpool.h"
 
-apr_pool_t *gAPRPoolp = NULL; // Global APR memory pool
-LLVolatileAPRPool *LLAPRFile::sAPRFilePoolp = NULL ; //global volatile APR memory pool.
-apr_thread_mutex_t *gLogMutexp = NULL;
-apr_thread_mutex_t *gCallStacksLogMutexp = NULL;
-
-const S32 FULL_VOLATILE_APR_POOL = 1024 ; //number of references to LLVolatileAPRPool
-
-void ll_init_apr()
-{
-	if (!gAPRPoolp)
-	{
-		// Initialize APR and create the global pool
-		apr_initialize();
-		apr_pool_create(&gAPRPoolp, NULL);
-		
-		// Initialize the logging mutex
-		apr_thread_mutex_create(&gLogMutexp, APR_THREAD_MUTEX_UNNESTED, gAPRPoolp);
-		apr_thread_mutex_create(&gCallStacksLogMutexp, APR_THREAD_MUTEX_UNNESTED, gAPRPoolp);
-	}
-
-	if(!LLAPRFile::sAPRFilePoolp)
-	{
-		LLAPRFile::sAPRFilePoolp = new LLVolatileAPRPool(FALSE) ;
-	}
-}
-
-
-void ll_cleanup_apr()
-{
-	LL_INFOS("APR") << "Cleaning up APR" << LL_ENDL;
-
-	if (gLogMutexp)
-	{
-		// Clean up the logging mutex
-
-		// All other threads NEED to be done before we clean up APR, so this is okay.
-		apr_thread_mutex_destroy(gLogMutexp);
-		gLogMutexp = NULL;
-	}
-	if (gCallStacksLogMutexp)
-	{
-		// Clean up the logging mutex
-
-		// All other threads NEED to be done before we clean up APR, so this is okay.
-		apr_thread_mutex_destroy(gCallStacksLogMutexp);
-		gCallStacksLogMutexp = NULL;
-	}
-	if (gAPRPoolp)
-	{
-		apr_pool_destroy(gAPRPoolp);
-		gAPRPoolp = NULL;
-	}
-	if (LLAPRFile::sAPRFilePoolp)
-	{
-		delete LLAPRFile::sAPRFilePoolp ;
-		LLAPRFile::sAPRFilePoolp = NULL ;
-	}
-	apr_terminate();
-}
-
-//
-//
-//LLAPRPool
-//
-LLAPRPool::LLAPRPool(apr_pool_t *parent, apr_size_t size, BOOL releasePoolFlag) 	
-	: mParent(parent),
-	mReleasePoolFlag(releasePoolFlag),
-	mMaxSize(size),
-	mPool(NULL)
-{	
-	createAPRPool() ;
-}
-
-LLAPRPool::~LLAPRPool() 
-{
-	releaseAPRPool() ;
-}
-
-void LLAPRPool::createAPRPool()
-{
-	if(mPool)
-	{
-		return ;
-	}
-
-	mStatus = apr_pool_create(&mPool, mParent);
-	ll_apr_warn_status(mStatus) ;
-
-	if(mMaxSize > 0) //size is the number of blocks (which is usually 4K), NOT bytes.
-	{
-		apr_allocator_t *allocator = apr_pool_allocator_get(mPool); 
-		if (allocator) 
-		{ 
-			apr_allocator_max_free_set(allocator, mMaxSize) ;
-		}
-	}
-}
-
-void LLAPRPool::releaseAPRPool()
-{
-	if(!mPool)
-	{
-		return ;
-	}
-
-	if(!mParent || mReleasePoolFlag)
-	{
-		apr_pool_destroy(mPool) ;
-		mPool = NULL ;
-	}
-}
-
-//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)
-{
-	//create mutex
-	if(!is_local) //not a local apr_pool, that is: shared by multiple threads.
-	{
-		apr_pool_create(&mMutexPool, NULL); // Create a pool for mutex
-		apr_thread_mutex_create(&mMutexp, APR_THREAD_MUTEX_UNNESTED, mMutexPool);
-	}
-}
-
-LLVolatileAPRPool::~LLVolatileAPRPool()
-{
-	//delete mutex
-	if(mMutexp)
-	{
-		apr_thread_mutex_destroy(mMutexp);
-		apr_pool_destroy(mMutexPool);
-	}
-}
-
-//
-//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++ ;
-
-	if(!mPool)
-	{
-		createAPRPool() ;
-	}
-	
-	return mPool ;
-}
-
-void LLVolatileAPRPool::clearVolatileAPRPool() 
-{
-	LLScopedLock lock(mMutexp) ;
-
-	if(mNumActiveRef > 0)
-	{
-		mNumActiveRef--;
-		if(mNumActiveRef < 1)
-		{
-			if(isFull()) 
-			{
-				mNumTotalRef = 0 ;
-
-				//destroy the apr_pool.
-				releaseAPRPool() ;
-			}
-			else 
-			{
-				//This does not actually free the memory, 
-				//it just allows the pool to re-use this memory for the next allocation. 
-				apr_pool_clear(mPool) ;
-			}
-		}
-	}
-	else
-	{
-		llassert_always(mNumActiveRef > 0) ;
-	}
-
-	//paranoia check if the pool is jammed.
-	//will remove the check before going to release.
-	llassert_always(mNumTotalRef < (FULL_VOLATILE_APR_POOL << 2)) ;
-}
-
-BOOL LLVolatileAPRPool::isFull()
-{
-	return mNumTotalRef > FULL_VOLATILE_APR_POOL ;
-}
 //---------------------------------------------------------------------
 //
 // LLScopedLock
 //
 LLAPRFile::LLAPRFile()
 	: mFile(NULL),
-	  mCurrentFilePoolp(NULL)
+	  mVolatileFilePoolp(NULL),
+	  mRegularFilePoolp(NULL)
 {
 }
 
-LLAPRFile::LLAPRFile(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool)
+LLAPRFile::LLAPRFile(std::string const& filename, apr_int32_t flags, S32* sizep, access_t access_type)
 	: mFile(NULL),
-	  mCurrentFilePoolp(NULL)
+	  mVolatileFilePoolp(NULL),
+	  mRegularFilePoolp(NULL)
 {
-	open(filename, flags, pool);
+	open(filename, flags, access_type, sizep);
 }
 
 LLAPRFile::~LLAPRFile()
 		mFile = NULL ;
 	}
 
-	if(mCurrentFilePoolp)
+	if (mVolatileFilePoolp)
 	{
-		mCurrentFilePoolp->clearVolatileAPRPool() ;
-		mCurrentFilePoolp = NULL ;
+		mVolatileFilePoolp->clearVolatileAPRPool() ;
+		mVolatileFilePoolp = NULL ;
+	}
+
+	if (mRegularFilePoolp)
+	{
+		delete mRegularFilePoolp;
+		mRegularFilePoolp = NULL;
 	}
 
 	return ret ;
 }
 
-apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool, S32* sizep)
+apr_status_t LLAPRFile::open(std::string const& filename, apr_int32_t flags, access_t access_type, S32* sizep)
 {
-	apr_status_t s ;
+	llassert_always(!mFile);
+	llassert_always(!mVolatileFilePoolp && !mRegularFilePoolp);
 
-	//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)
+	apr_status_t status;
+	{
+		apr_pool_t* apr_file_open_pool;	// The use of apr_pool_t is OK here.
+										// This is a temporary variable for a pool that is passed directly to apr_file_open below.
+		if (access_type == short_lived)
+		{
+			// Use a "volatile" thread-local pool.
+			mVolatileFilePoolp = &LLThreadLocalData::tldata().mVolatileAPRPool;
+			// Access the pool and increment its reference count.
+			// The reference count of LLVolatileAPRPool objects will be decremented
+			// again in LLAPRFile::close by calling mVolatileFilePoolp->clearVolatileAPRPool().
+			apr_file_open_pool = mVolatileFilePoolp->getVolatileAPRPool();
+		}
+		else
+		{
+			mRegularFilePoolp = new LLAPRPool(LLThreadLocalData::tldata().mRootPool);
+			apr_file_open_pool = (*mRegularFilePoolp)();
+		}
+		status = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, apr_file_open_pool);
+	}
+	if (status != APR_SUCCESS || !mFile)
 	{
 		mFile = NULL ;
-		
+		close() ;
 		if (sizep)
 		{
 			*sizep = 0;
 		}
+		return status;
 	}
-	else if (sizep)
+
+	if (sizep)
 	{
 		S32 file_size = 0;
 		apr_off_t offset = 0;
 		*sizep = file_size;
 	}
 
-	if(!mCurrentFilePoolp)
-	{
-		mCurrentFilePoolp = pool ;
-
-		if(!mFile)
-		{
-			close() ;
-		}
-	}
-
-	return s ;
-}
-
-//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, gAPRPoolp);
-	if (s != APR_SUCCESS || !mFile)
-	{
-		mFile = NULL ;
-		close() ;
-		return s;
-	}
-
-	return s;
-}
-
-apr_pool_t* LLAPRFile::getAPRFilePool(apr_pool_t* pool)
-{	
-	if(!pool)
-	{
-		mCurrentFilePoolp = sAPRFilePoolp ;
-		return mCurrentFilePoolp->getVolatileAPRPool() ;
-	}
-
-	return pool ;
+	return status;
 }
 
 // File I/O
 //
 
 //static
-apr_status_t LLAPRFile::close(apr_file_t* file_handle, LLVolatileAPRPool* pool) 
-{
-	apr_status_t ret = APR_SUCCESS ;
-	if(file_handle)
-	{
-		ret = apr_file_close(file_handle);
-		file_handle = NULL ;
-	}
-
-	if(pool)
-	{
-		pool->clearVolatileAPRPool() ;
-	}
-
-	return ret ;
-}
-
-//static
-apr_file_t* LLAPRFile::open(const std::string& filename, LLVolatileAPRPool* pool, apr_int32_t flags)
-{
-	apr_status_t s;
-	apr_file_t* file_handle ;
-
-	pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
-
-	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;
-	}
-
-	return file_handle ;
-}
-
-//static
 S32 LLAPRFile::seek(apr_file_t* file_handle, apr_seek_where_t where, S32 offset)
 {
 	if(!file_handle)
 }
 
 //static
-S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool)
+S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes)
 {
-	//*****************************************
-	apr_file_t* file_handle = open(filename, pool, APR_READ|APR_BINARY); 
-	//*****************************************	
-	if (!file_handle)
+	apr_file_t* file_handle;
+	LLScopedVolatileAPRPool pool;
+	apr_status_t s = apr_file_open(&file_handle, filename.c_str(), APR_READ|APR_BINARY, APR_OS_DEFAULT, pool);
+	if (s != APR_SUCCESS || !file_handle)
 	{
+		ll_apr_warn_status(s);
+		LL_WARNS("APR") << " while attempting to open file \"" << filename << '"' << LL_ENDL;
 		return 0;
 	}
 
 		}
 	}
 	
-	//*****************************************
-	close(file_handle, pool) ; 
-	//*****************************************
+	apr_file_close(file_handle);
+
 	return (S32)bytes_read;
 }
 
 //static
-S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool)
+S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes)
 {
 	apr_int32_t flags = APR_CREATE|APR_WRITE|APR_BINARY;
 	if (offset < 0)
 		offset = 0;
 	}
 	
-	//*****************************************
-	apr_file_t* file_handle = open(filename, pool, flags);
-	//*****************************************
-	if (!file_handle)
+	apr_file_t* file_handle;
+	LLScopedVolatileAPRPool pool;
+	apr_status_t s = apr_file_open(&file_handle, filename.c_str(), flags, APR_OS_DEFAULT, pool);
+	if (s != APR_SUCCESS || !file_handle)
 	{
+		ll_apr_warn_status(s);
+		LL_WARNS("APR") << " while attempting to open file \"" << filename << '"' << LL_ENDL;
 		return 0;
 	}
 
 		}
 	}
 
-	//*****************************************
-	LLAPRFile::close(file_handle, pool);
-	//*****************************************
+	apr_file_close(file_handle);
 
 	return (S32)bytes_written;
 }
 
 //static
-bool LLAPRFile::remove(const std::string& filename, LLVolatileAPRPool* pool)
+bool LLAPRFile::remove(const std::string& filename)
 {
 	apr_status_t s;
 
-	pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
-	s = apr_file_remove(filename.c_str(), pool->getVolatileAPRPool());
-	pool->clearVolatileAPRPool() ;
+	LLScopedVolatileAPRPool pool;
+	s = apr_file_remove(filename.c_str(), pool);
 
 	if (s != APR_SUCCESS)
 	{
 }
 
 //static
-bool LLAPRFile::rename(const std::string& filename, const std::string& newname, LLVolatileAPRPool* pool)
+bool LLAPRFile::rename(const std::string& filename, const std::string& newname)
 {
 	apr_status_t s;
 
-	pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
-	s = apr_file_rename(filename.c_str(), newname.c_str(), pool->getVolatileAPRPool());
-	pool->clearVolatileAPRPool() ;
+	LLScopedVolatileAPRPool pool;
+	s = apr_file_rename(filename.c_str(), newname.c_str(), pool);
 	
 	if (s != APR_SUCCESS)
 	{
 }
 
 //static
-bool LLAPRFile::isExist(const std::string& filename, LLVolatileAPRPool* pool, apr_int32_t flags)
+bool LLAPRFile::isExist(const std::string& filename, apr_int32_t flags)
 {
-	apr_file_t* apr_file;
+	apr_file_t* file_handle;
 	apr_status_t s;
 
-	pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
-	s = apr_file_open(&apr_file, filename.c_str(), flags, APR_OS_DEFAULT, pool->getVolatileAPRPool());	
+	LLScopedVolatileAPRPool pool;
+	s = apr_file_open(&file_handle, filename.c_str(), flags, APR_OS_DEFAULT, pool);
 
-	if (s != APR_SUCCESS || !apr_file)
+	if (s != APR_SUCCESS || !file_handle)
 	{
-		pool->clearVolatileAPRPool() ;
 		return false;
 	}
 	else
 	{
-		apr_file_close(apr_file) ;
-		pool->clearVolatileAPRPool() ;
+		apr_file_close(file_handle);
 		return true;
 	}
 }
 
 //static
-S32 LLAPRFile::size(const std::string& filename, LLVolatileAPRPool* pool)
+S32 LLAPRFile::size(const std::string& filename)
 {
-	apr_file_t* apr_file;
+	apr_file_t* file_handle;
 	apr_finfo_t info;
 	apr_status_t s;
 	
-	pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
-	s = apr_file_open(&apr_file, filename.c_str(), APR_READ, APR_OS_DEFAULT, pool->getVolatileAPRPool());
+	LLScopedVolatileAPRPool pool;
+	s = apr_file_open(&file_handle, filename.c_str(), APR_READ, APR_OS_DEFAULT, pool);
 	
-	if (s != APR_SUCCESS || !apr_file)
+	if (s != APR_SUCCESS || !file_handle)
 	{		
-		pool->clearVolatileAPRPool() ;
-		
 		return 0;
 	}
 	else
 	{
-		apr_status_t s = apr_file_info_get(&info, APR_FINFO_SIZE, apr_file);		
+		apr_status_t s = apr_file_info_get(&info, APR_FINFO_SIZE, file_handle);
 
-		apr_file_close(apr_file) ;
-		pool->clearVolatileAPRPool() ;
+		apr_file_close(file_handle) ;
 		
 		if (s == APR_SUCCESS)
 		{
 }
 
 //static
-bool LLAPRFile::makeDir(const std::string& dirname, LLVolatileAPRPool* pool)
+bool LLAPRFile::makeDir(const std::string& dirname)
 {
 	apr_status_t s;
 
-	pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
-	s = apr_dir_make(dirname.c_str(), APR_FPROT_OS_DEFAULT, pool->getVolatileAPRPool());
-	pool->clearVolatileAPRPool() ;
+	LLScopedVolatileAPRPool pool;
+	s = apr_dir_make(dirname.c_str(), APR_FPROT_OS_DEFAULT, pool);
 		
 	if (s != APR_SUCCESS)
 	{
 		ll_apr_warn_status(s);
-		LL_WARNS("APR") << " Attempting to make directory: " << dirname << LL_ENDL;
+		LL_WARNS("APR") << " while attempting to make directory: " << dirname << LL_ENDL;
 		return false;
 	}
 	return true;
 }
 
 //static
-bool LLAPRFile::removeDir(const std::string& dirname, LLVolatileAPRPool* pool)
+bool LLAPRFile::removeDir(const std::string& dirname)
 {
 	apr_status_t s;
 
-	pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
-	s = apr_file_remove(dirname.c_str(), pool->getVolatileAPRPool());
-	pool->clearVolatileAPRPool() ;
+	LLScopedVolatileAPRPool pool;
+	s = apr_file_remove(dirname.c_str(), pool);
 	
 	if (s != APR_SUCCESS)
 	{

indra/llcommon/llapr.h

 #include "apr_atomic.h"
 #include "llstring.h"
 
-extern LL_COMMON_API apr_thread_mutex_t* gLogMutexp;
-extern apr_thread_mutex_t* gCallStacksLogMutexp;
-
 struct apr_dso_handle_t;
-
-/** 
- * @brief initialize the common apr constructs -- apr itself, the
- * global pool, and a mutex.
- */
-void LL_COMMON_API ll_init_apr();
-
-/** 
- * @brief Cleanup those common apr constructs.
- */
-void LL_COMMON_API ll_cleanup_apr();
-
-//
-//LL apr_pool
-//manage apr_pool_t, destroy allocated apr_pool in the destruction function.
-//
-class LL_COMMON_API LLAPRPool
-{
-public:
-	LLAPRPool(apr_pool_t *parent = NULL, apr_size_t size = 0, BOOL releasePoolFlag = TRUE) ;
-	virtual ~LLAPRPool() ;
-
-	virtual apr_pool_t* getAPRPool() ;
-	apr_status_t getStatus() {return mStatus ; }
-
-protected:
-	void releaseAPRPool() ;
-	void createAPRPool() ;
-
-protected:
-	apr_pool_t*  mPool ;              //pointing to an apr_pool
-	apr_pool_t*  mParent ;			  //parent pool
-	apr_size_t   mMaxSize ;           //max size of mPool, mPool should return memory to system if allocated memory beyond this limit. However it seems not to work.
-	apr_status_t mStatus ;            //status when creating the pool
-	BOOL         mReleasePoolFlag ;   //if set, mPool is destroyed when LLAPRPool is deleted. default value is true.
-};
-
-//
-//volatile LL apr_pool
-//which clears memory automatically.
-//so it can not hold static data or data after memory is cleared
-//
-class LL_COMMON_API LLVolatileAPRPool : public LLAPRPool
-{
-public:
-	LLVolatileAPRPool(BOOL is_local = TRUE, apr_pool_t *parent = NULL, apr_size_t size = 0, BOOL releasePoolFlag = TRUE);
-	virtual ~LLVolatileAPRPool();
-
-	/*virtual*/ apr_pool_t* getAPRPool() ; //define this virtual function to avoid any mistakenly calling LLAPRPool::getAPRPool().
-	apr_pool_t* getVolatileAPRPool() ;	
-	void        clearVolatileAPRPool() ;
-
-	BOOL        isFull() ;
-	
-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.  
-
-	apr_thread_mutex_t *mMutexp;
-	apr_pool_t         *mMutexPool;
-} ;
+class LLAPRPool;
+class LLVolatileAPRPool;
 
 /** 
  * @class LLScopedLock
 	// 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. 
+	LLVolatileAPRPool* mVolatileFilePoolp;	// (Thread local) APR pool currently in use.
+	LLAPRPool* mRegularFilePoolp;		// ...or a regular pool.
 
 public:
+	enum access_t {
+		long_lived,		// Use a global pool for long-lived file accesses.
+		short_lived		// Use a volatile pool for short-lived file accesses.
+	};
+
 	LLAPRFile() ;
-	LLAPRFile(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool = NULL);
+	LLAPRFile(std::string const& filename, apr_int32_t flags, S32* sizep = NULL, access_t access_type = short_lived);
 	~LLAPRFile() ;
-	
-	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 open(const std::string& filename, apr_int32_t flags, access_t access_type, S32* sizep = NULL);
 	apr_status_t close() ;
 
 	// Returns actual offset, -1 if seek fails
 	
 	apr_file_t* getFileHandle() {return mFile;}	
 
-private:
-	apr_pool_t* getAPRFilePool(apr_pool_t* pool) ;	
-	
 //
 //*******************************************************************************************************************************
 //static components
 //
-public:
-	static LLVolatileAPRPool *sAPRFilePoolp ; //a global apr_pool for APRFile, which is used only when local pool does not exist.
-
 private:
-	static apr_file_t* open(const std::string& filename, LLVolatileAPRPool* pool, apr_int32_t flags);
-	static apr_status_t close(apr_file_t* file, LLVolatileAPRPool* pool) ;
 	static S32 seek(apr_file_t* file, apr_seek_where_t where, S32 offset);
 public:
 	// returns false if failure:
-	static bool remove(const std::string& filename, LLVolatileAPRPool* pool = NULL);
-	static bool rename(const std::string& filename, const std::string& newname, LLVolatileAPRPool* pool = NULL);
-	static bool isExist(const std::string& filename, LLVolatileAPRPool* pool = NULL, apr_int32_t flags = APR_READ);
-	static S32 size(const std::string& filename, LLVolatileAPRPool* pool = NULL);
-	static bool makeDir(const std::string& dirname, LLVolatileAPRPool* pool = NULL);
-	static bool removeDir(const std::string& dirname, LLVolatileAPRPool* pool = NULL);
+	static bool remove(const std::string& filename);
+	static bool rename(const std::string& filename, const std::string& newname);
+	static bool isExist(const std::string& filename, apr_int32_t flags = APR_READ);
+	static S32 size(const std::string& filename);
+	static bool makeDir(const std::string& dirname);
+	static bool removeDir(const std::string& dirname);
 
 	// Returns bytes read/written, 0 if read/write fails:
-	static S32 readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool = NULL);	
-	static S32 writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool = NULL); // offset<0 means append
+	static S32 readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes);	
+	static S32 writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes); // offset<0 means append
 //*******************************************************************************************************************************
 };
 
 void LL_COMMON_API ll_apr_assert_status(apr_status_t status);
 void LL_COMMON_API ll_apr_assert_status(apr_status_t status, apr_dso_handle_t* handle);
 
-extern "C" LL_COMMON_API apr_pool_t* gAPRPoolp; // Global APR memory pool
-
 #endif // LL_LLAPR_H

indra/llcommon/llaprpool.cpp

+/**
+ * @file llaprpool.cpp
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ *
+ * CHANGELOG
+ *   and additional copyright holders.
+ *
+ *   04/04/2010
+ *   - Initial version, written by Aleric Inglewood @ SL
+ *
+ *   10/11/2010
+ *   - Added APR_HAS_THREADS #if's to allow creation and destruction
+ *     of subpools by threads other than the parent pool owner.
+ */
+
+#include "linden_common.h"
+
+#include "llerror.h"
+#include "llaprpool.h"
+#include "llthread.h"
+
+// Create a subpool from parent.
+void LLAPRPool::create(LLAPRPool& parent)
+{
+	llassert(!mPool);			// Must be non-initialized.
+	mParent = &parent;
+	if (!mParent)				// Using the default parameter?
+	{
+		// By default use the root pool of the current thread.
+		mParent = &LLThreadLocalData::tldata().mRootPool;
+	}
+	llassert(mParent->mPool);	// Parent must be initialized.
+#if APR_HAS_THREADS
+	// As per the documentation of APR (ie http://apr.apache.org/docs/apr/1.4/apr__pools_8h.html):
+	//
+	// Note that most operations on pools are not thread-safe: a single pool should only be
+	// accessed by a single thread at any given time. The one exception to this rule is creating
+	// a subpool of a given pool: one or more threads can safely create subpools at the same
+	// time that another thread accesses the parent pool.
+	//
+	// In other words, it's safe for any thread to create a (sub)pool, independent of who
+	// owns the parent pool.
+	mOwner = apr_os_thread_current();
+#else
+	mOwner = mParent->mOwner;
+	llassert(apr_os_thread_equal(mOwner, apr_os_thread_current()));
+#endif
+	apr_status_t const apr_pool_create_status = apr_pool_create(&mPool, mParent->mPool);
+	llassert_always(apr_pool_create_status == APR_SUCCESS);
+	llassert(mPool);			// Initialized.
+	apr_pool_cleanup_register(mPool, this, &s_plain_cleanup, &apr_pool_cleanup_null);
+}
+
+// Destroy the (sub)pool, if any.
+void LLAPRPool::destroy(void)
+{
+	// Only do anything if we are not already (being) destroyed.
+	if (mPool)
+	{
+#if !APR_HAS_THREADS
+		// If we are a root pool, then every thread may destruct us: in that case
+		// we have to assume that no other thread will use this pool concurrently,
+		// of course. Otherwise, if we are a subpool, only the thread that owns
+		// the parent may destruct us, since that is the pool that is still alive,
+		// possibly being used by others and being altered here.
+		llassert(!mParent || apr_os_thread_equal(mParent->mOwner, apr_os_thread_current()));
+#endif
+		apr_pool_t* pool = mPool;	// The use of apr_pool_t is OK here.
+									// Temporary store before destroying the pool.
+		mPool = NULL;				// Mark that we are BEING destructed.
+		apr_pool_cleanup_kill(pool, this, &s_plain_cleanup);
+		apr_pool_destroy(pool);
+	}
+}
+
+bool LLAPRPool::parent_is_being_destructed(void)
+{
+	return mParent && (!mParent->mPool || mParent->parent_is_being_destructed());
+}
+
+LLAPRInitialization::LLAPRInitialization(void)
+{
+	static bool apr_initialized = false;
+
+	if (!apr_initialized)
+	{
+		apr_initialize();
+	}
+
+	apr_initialized = true;
+}
+
+bool LLAPRRootPool::sCountInitialized = false;
+apr_uint32_t volatile LLAPRRootPool::sCount;
+
+apr_thread_mutex_t* gLogMutexp;
+apr_thread_mutex_t* gCallStacksLogMutexp;
+
+LLAPRRootPool::LLAPRRootPool(void) : LLAPRInitialization(), LLAPRPool(0)
+{
+	// sCountInitialized don't need locking because when we get here there is still only a single thread.
+	if (!sCountInitialized)
+	{
+		// Initialize the logging mutex
+		apr_thread_mutex_create(&gLogMutexp, APR_THREAD_MUTEX_UNNESTED, mPool);
+		apr_thread_mutex_create(&gCallStacksLogMutexp, APR_THREAD_MUTEX_UNNESTED, mPool);
+
+		apr_status_t status = apr_atomic_init(mPool);
+		llassert_always(status == APR_SUCCESS);
+		apr_atomic_set32(&sCount, 1);	// Set to 1 to account for the global root pool.
+		sCountInitialized = true;
+
+		// Initialize thread-local APR pool support.
+		// Because this recursively calls LLAPRRootPool::LLAPRRootPool(void)
+		// it must be done last, so that sCount is already initialized.
+		LLThreadLocalData::init();
+	}
+	apr_atomic_inc32(&sCount);
+}
+
+LLAPRRootPool::~LLAPRRootPool()
+{
+	if (!apr_atomic_dec32(&sCount))
+	{
+		// The last pool was destructed. Cleanup remainder of APR.
+		LL_INFOS("APR") << "Cleaning up APR" << LL_ENDL;
+
+		if (gLogMutexp)
+		{
+			// Clean up the logging mutex
+
+			// All other threads NEED to be done before we clean up APR, so this is okay.
+			apr_thread_mutex_destroy(gLogMutexp);
+			gLogMutexp = NULL;
+		}
+		if (gCallStacksLogMutexp)
+		{
+			// Clean up the logging mutex
+
+			// All other threads NEED to be done before we clean up APR, so this is okay.
+			apr_thread_mutex_destroy(gCallStacksLogMutexp);
+			gCallStacksLogMutexp = NULL;
+		}
+
+		// Must destroy ALL, and therefore this last LLAPRRootPool, before terminating APR.
+		static_cast<LLAPRRootPool*>(this)->destroy();
+
+		apr_terminate();
+	}
+}
+
+//static
+// Return a global root pool that is independent of LLThreadLocalData.
+// Normally you should NOT use this. Only use for early initialization
+// (before main) and deinitialization (after main).
+LLAPRRootPool& LLAPRRootPool::get(void)
+{
+  static LLAPRRootPool global_APRpool(0);
+  return global_APRpool;
+}
+
+void LLVolatileAPRPool::clearVolatileAPRPool()
+{
+	llassert_always(mNumActiveRef > 0);
+	if (--mNumActiveRef == 0)
+	{
+		if (isOld())
+		{
+			destroy();
+			mNumTotalRef = 0 ;
+		}
+		else
+		{
+			// This does not actually free the memory,
+			// it just allows the pool to re-use this memory for the next allocation.
+			clear();
+		}
+	}
+
+	// Paranoia check if the pool is jammed.
+	llassert(mNumTotalRef < (FULL_VOLATILE_APR_POOL << 2)) ;
+}

indra/llcommon/llaprpool.h

+/**
+ * @file llaprpool.h
+ * @brief Implementation of LLAPRPool
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *