diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 7ed1671ca827ffd5f672e3647439fc796aeca142..f8f1c010f7034562b76e678cc6304ad5de7da984 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -98,6 +98,7 @@ set(llcommon_SOURCE_FILES
     llstringtable.cpp
     llsys.cpp
     llthread.cpp
+	llthreadlocalstorage.cpp
     llthreadsafequeue.cpp
     lltimer.cpp
     lltrace.cpp
diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp
index 0556fadb266e15ff2e6224eb3131f584e6ceb79e..47fa70614fa78fb15f48b325c13745a20f3cb870 100644
--- a/indra/llcommon/llapr.cpp
+++ b/indra/llcommon/llapr.cpp
@@ -493,77 +493,6 @@ S32 LLAPRFile::seek(apr_seek_where_t where, S32 offset)
 	return LLAPRFile::seek(mFile, where, offset) ;
 }
 
-//
-//LLThreadLocalPointerBase
-//
-bool LLThreadLocalPointerBase::sInitialized = false;
-
-void LLThreadLocalPointerBase::set( void* value )
-{
-	llassert(sInitialized && mThreadKey);
-
-	apr_status_t result = apr_threadkey_private_set((void*)value, mThreadKey);
-	if (result != APR_SUCCESS)
-	{
-		ll_apr_warn_status(result);
-		llerrs << "Failed to set thread local data" << llendl;
-	}
-}
-
-void LLThreadLocalPointerBase::initStorage( )
-{
-	apr_status_t result = apr_threadkey_private_create(&mThreadKey, NULL, gAPRPoolp);
-	if (result != APR_SUCCESS)
-	{
-		ll_apr_warn_status(result);
-		llerrs << "Failed to allocate thread local data" << llendl;
-	}
-}
-
-void LLThreadLocalPointerBase::destroyStorage()
-{
-	if (sInitialized)
-	{
-		if (mThreadKey)
-		{
-			apr_status_t result = apr_threadkey_private_delete(mThreadKey);
-			if (result != APR_SUCCESS)
-			{
-				ll_apr_warn_status(result);
-				llerrs << "Failed to delete thread local data" << llendl;
-			}
-		}
-	}
-}
-
-void LLThreadLocalPointerBase::initAllThreadLocalStorage()
-{
-	if (!sInitialized)
-	{
-		for (LLInstanceTracker<LLThreadLocalPointerBase>::instance_iter it = beginInstances(), end_it = endInstances();
-			it != end_it;
-			++it)
-		{
-			(*it).initStorage();
-		}
-		sInitialized = true;
-	}
-}
-
-void LLThreadLocalPointerBase::destroyAllThreadLocalStorage()
-{
-	if (sInitialized)
-	{
-		//for (LLInstanceTracker<LLThreadLocalPointerBase>::instance_iter it = beginInstances(), end_it = endInstances();
-		//	it != end_it;
-		//	++it)
-		//{
-		//	(*it).destroyStorage();
-		//}
-		sInitialized = false;
-	}
-}
-
 //
 //*******************************************************************************************************************************
 //static components of LLAPRFile
diff --git a/indra/llcommon/llthreadlocalstorage.cpp b/indra/llcommon/llthreadlocalstorage.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7858ee542950feb78594b9e4ec4f6a791e5f9f98
--- /dev/null
+++ b/indra/llcommon/llthreadlocalstorage.cpp
@@ -0,0 +1,101 @@
+/** 
+ * @file llthreadlocalstorage.cpp
+ * @author Richard
+ * @date 2013-1-11
+ * @brief implementation of thread local storage utility classes
+ *
+ * $LicenseInfo:firstyear=2013&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, 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$
+ */
+
+#include "linden_common.h"
+#include "llthreadlocalstorage.h"
+
+//
+//LLThreadLocalPointerBase
+//
+bool LLThreadLocalPointerBase::sInitialized = false;
+
+void LLThreadLocalPointerBase::set( void* value )
+{
+	llassert(sInitialized && mThreadKey);
+
+	apr_status_t result = apr_threadkey_private_set((void*)value, mThreadKey);
+	if (result != APR_SUCCESS)
+	{
+		ll_apr_warn_status(result);
+		llerrs << "Failed to set thread local data" << llendl;
+	}
+}
+
+void LLThreadLocalPointerBase::initStorage( )
+{
+	apr_status_t result = apr_threadkey_private_create(&mThreadKey, NULL, gAPRPoolp);
+	if (result != APR_SUCCESS)
+	{
+		ll_apr_warn_status(result);
+		llerrs << "Failed to allocate thread local data" << llendl;
+	}
+}
+
+void LLThreadLocalPointerBase::destroyStorage()
+{
+	if (sInitialized)
+	{
+		if (mThreadKey)
+		{
+			apr_status_t result = apr_threadkey_private_delete(mThreadKey);
+			if (result != APR_SUCCESS)
+			{
+				ll_apr_warn_status(result);
+				llerrs << "Failed to delete thread local data" << llendl;
+			}
+		}
+	}
+}
+
+void LLThreadLocalPointerBase::initAllThreadLocalStorage()
+{
+	if (!sInitialized)
+	{
+		for (LLInstanceTracker<LLThreadLocalPointerBase>::instance_iter it = beginInstances(), end_it = endInstances();
+			it != end_it;
+			++it)
+		{
+			(*it).initStorage();
+		}
+		sInitialized = true;
+	}
+}
+
+void LLThreadLocalPointerBase::destroyAllThreadLocalStorage()
+{
+	if (sInitialized)
+	{
+		//for (LLInstanceTracker<LLThreadLocalPointerBase>::instance_iter it = beginInstances(), end_it = endInstances();
+		//	it != end_it;
+		//	++it)
+		//{
+		//	(*it).destroyStorage();
+		//}
+		sInitialized = false;
+	}
+}