diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index d9eb13d65a6ece0a5289a8d2d1c8a87da03aa0df..ac19e6d025131df3bba6feed43b41b99682ecbcb 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -35,6 +35,7 @@ set(llcommon_SOURCE_FILES
     llapp.cpp
     llapr.cpp
     llassettype.cpp
+    llatomic.cpp
     llbase32.cpp
     llbase64.cpp
     llbitpack.cpp
@@ -135,6 +136,7 @@ set(llcommon_HEADER_FILES
     llapp.h
     llapr.h
     llassettype.h
+    llatomic.h
     llbase32.h
     llbase64.h
     llbitpack.h
diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h
index acd829d8649ae6a0883be66338014267ef3d82ee..245c73e3a2210fddc818fae52aaba3ddb6d64433 100644
--- a/indra/llcommon/llapp.h
+++ b/indra/llcommon/llapp.h
@@ -30,9 +30,8 @@
 #include <map>
 #include "llrun.h"
 #include "llsd.h"
+#include <atomic>
 // Forward declarations
-template <typename Type> class LLAtomic32;
-typedef LLAtomic32<U32> LLAtomicU32;
 class LLErrorThread;
 class LLLiveFile;
 #if LL_LINUX
diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h
index 73d1d180efe9b78da0dd864a5235b0af62fdd054..da50dda103084fbd7d881459a12774a3ff36d264 100644
--- a/indra/llcommon/llapr.h
+++ b/indra/llcommon/llapr.h
@@ -38,7 +38,6 @@
 #include "apr_thread_proc.h"
 #include "apr_getopt.h"
 #include "apr_signal.h"
-#include "apr_atomic.h"
 
 #include "llstring.h"
 
@@ -131,33 +130,6 @@ class LL_COMMON_API LLVolatileAPRPool : public LLAPRPool
 	std::unique_ptr<std::mutex> mMutexp;
 } ;
 
-template <typename Type> class LLAtomic32
-{
-public:
-	LLAtomic32<Type>() {};
-	LLAtomic32<Type>(Type x) {apr_atomic_set32(&mData, apr_uint32_t(x)); };
-	~LLAtomic32<Type>() {};
-
-	operator const Type() { apr_uint32_t data = apr_atomic_read32(&mData); return Type(data); }
-	
-	Type	CurrentValue() const { apr_uint32_t data = apr_atomic_read32(const_cast< volatile apr_uint32_t* >(&mData)); return Type(data); }
-
-	Type operator =(const Type& x) { apr_atomic_set32(&mData, apr_uint32_t(x)); return Type(mData); }
-	void operator -=(Type x) { apr_atomic_sub32(&mData, apr_uint32_t(x)); }
-	void operator +=(Type x) { apr_atomic_add32(&mData, apr_uint32_t(x)); }
-	Type operator ++(int) { return apr_atomic_inc32(&mData); } // Type++
-	Type operator --(int) { return apr_atomic_dec32(&mData); } // approximately --Type (0 if final is 0, non-zero otherwise)
-
-	Type operator ++() { return apr_atomic_inc32(&mData); } // Type++
-	Type operator --() { return apr_atomic_dec32(&mData); } // approximately --Type (0 if final is 0, non-zero otherwise)
-	
-private:
-	volatile apr_uint32_t mData;
-};
-
-typedef LLAtomic32<U32> LLAtomicU32;
-typedef LLAtomic32<S32> LLAtomicS32;
-
 // File IO convenience functions.
 // Returns NULL if the file fails to open, sets *sizep to file size if not NULL
 // abbreviated flags
diff --git a/indra/llcommon/llatomic.cpp b/indra/llcommon/llatomic.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..93aba1f46058bf0e57526178293944bd8b1bfaee
--- /dev/null
+++ b/indra/llcommon/llatomic.cpp
@@ -0,0 +1,28 @@
+/** 
+ * @file llatomic.cpp
+ *
+ * $LicenseInfo:firstyear=2018&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2018, 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 "llatomic.h"
+
+//============================================================================
diff --git a/indra/llcommon/llatomic.h b/indra/llcommon/llatomic.h
new file mode 100644
index 0000000000000000000000000000000000000000..8de773846c46c802582eea78050e7172a09d1e3a
--- /dev/null
+++ b/indra/llcommon/llatomic.h
@@ -0,0 +1,69 @@
+/** 
+ * @file llatomic.h
+ * @brief Base classes for atomic.
+ *
+ * $LicenseInfo:firstyear=2018&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2018, 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_LLATOMIC_H
+#define LL_LLATOMIC_H
+
+#include "stdtypes.h"
+
+#include <atomic>
+
+template <typename Type, typename AtomicType = std::atomic< Type > > class LLAtomicBase
+{
+public:
+    LLAtomicBase() {};
+    LLAtomicBase(Type x) { mData.store(x); }
+    ~LLAtomicBase() {};
+
+    operator const Type() { return mData; }
+
+    Type	CurrentValue() const { return mData; }
+
+    Type operator =(const Type& x) { mData.store(x); return mData; }
+    void operator -=(Type x) { mData -= x; }
+    void operator +=(Type x) { mData += x; }
+    Type operator ++(int) { return mData++; }
+    Type operator --(int) { return mData--; }
+
+    Type operator ++() { return ++mData; }
+    Type operator --() { return --mData; }
+
+private:
+    AtomicType mData;
+};
+
+// Typedefs for specialized versions. Using std::atomic_(u)int32_t to get the optimzed implementation.
+#ifdef LL_WINDOWS
+typedef LLAtomicBase<U32, std::atomic_uint32_t> LLAtomicU32;
+typedef LLAtomicBase<S32, std::atomic_int32_t> LLAtomicS32;
+#else
+typedef LLAtomicBase<U32, std::atomic_uint> LLAtomicU32;
+typedef LLAtomicBase<S32, std::atomic_int> LLAtomicS32;
+#endif
+
+typedef LLAtomicBase<bool, std::atomic_bool> LLAtomicBool;
+
+#endif // LL_LLATOMIC_H
diff --git a/indra/llcommon/llinstancetracker.cpp b/indra/llcommon/llinstancetracker.cpp
index 11fc53f8c88edbf717270ceb5976a7c900bdbbbe..3f990f4869c3a504bb9a9c7d656d64a90e5c8279 100644
--- a/indra/llcommon/llinstancetracker.cpp
+++ b/indra/llcommon/llinstancetracker.cpp
@@ -36,17 +36,16 @@
 
 void LLInstanceTrackerBase::StaticBase::incrementDepth()
 {
-	apr_atomic_inc32(&sIterationNestDepth);
+	++sIterationNestDepth;
 }
 
 void LLInstanceTrackerBase::StaticBase::decrementDepth()
 {
 	llassert(sIterationNestDepth);
-	apr_atomic_dec32(&sIterationNestDepth);
+	--sIterationNestDepth;
 }
 
 U32 LLInstanceTrackerBase::StaticBase::getDepth()
 {
-	apr_uint32_t data = apr_atomic_read32(&sIterationNestDepth);
-	return data;
+	return sIterationNestDepth;
 }
diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h
index 910c8dbd99cdebb677e5a157dd725d3c74553459..363d0bcbd58ce3eeb7ec096e98396863744e232b 100644
--- a/indra/llcommon/llinstancetracker.h
+++ b/indra/llcommon/llinstancetracker.h
@@ -28,6 +28,7 @@
 #ifndef LL_LLINSTANCETRACKER_H
 #define LL_LLINSTANCETRACKER_H
 
+#include <atomic>
 #include <map>
 #include <typeinfo>
 
@@ -81,8 +82,12 @@ class LL_COMMON_API LLInstanceTrackerBase
 		void decrementDepth();
 		U32 getDepth();
 	private:
-		U32 sIterationNestDepth;
-    };
+#ifdef LL_WINDOWS
+		std::atomic_uint32_t sIterationNestDepth;
+#else
+		std::atomic_uint sIterationNestDepth;
+#endif
+	};
 };
 
 LL_COMMON_API void assert_main_thread();
diff --git a/indra/llcommon/llmutex.cpp b/indra/llcommon/llmutex.cpp
index cf84e50953caaa91e06bf4369f1a1a043ad207c4..75f43a47042f3b2226ce93602b8b55fc492dbf51 100644
--- a/indra/llcommon/llmutex.cpp
+++ b/indra/llcommon/llmutex.cpp
@@ -24,9 +24,6 @@
  */
 
 #include "linden_common.h"
-#include "llapr.h"
-
-#include "apr_portable.h"
 
 #include "llmutex.h"
 #include "llthread.h"
diff --git a/indra/llcommon/llqueuedthread.h b/indra/llcommon/llqueuedthread.h
index d3704b0fe22ad4e43d509e99901ebb6b215951aa..5d3f8736467fa7f6967d6d9017f53d7bd4d16227 100644
--- a/indra/llcommon/llqueuedthread.h
+++ b/indra/llcommon/llqueuedthread.h
@@ -32,7 +32,7 @@
 #include <map>
 #include <set>
 
-#include "llapr.h"
+#include "llatomic.h"
 
 #include "llthread.h"
 #include "llsimplehash.h"
@@ -128,7 +128,7 @@ class LL_COMMON_API LLQueuedThread : public LLThread
 		};
 		
 	protected:
-		LLAtomic32<status_t> mStatus;
+		LLAtomicBase<status_t> mStatus;
 		U32 mPriority;
 		U32 mFlags;
 	};
@@ -198,7 +198,7 @@ class LL_COMMON_API LLQueuedThread : public LLThread
 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
+	LLAtomicBool mIdleThread; // request queue is empty (or we are quitting) and the thread is idle
 	
 	typedef std::set<QueuedRequest*, queued_request_less> request_queue_t;
 	request_queue_t mRequestQueue;
diff --git a/indra/llcommon/llrefcount.h b/indra/llcommon/llrefcount.h
index cdc60fa54ffea34584b1d58fad85ebe2467dfe31..fb0411d27bfd76c39a8302be87bc67d4c3d483d0 100644
--- a/indra/llcommon/llrefcount.h
+++ b/indra/llcommon/llrefcount.h
@@ -29,7 +29,7 @@
 #include <boost/noncopyable.hpp>
 #include <boost/intrusive_ptr.hpp>
 #include "llmutex.h"
-#include "llapr.h"
+#include "llatomic.h"
 
 //----------------------------------------------------------------------------
 // RefCount objects should generally only be accessed by way of LLPointer<>'s
@@ -107,8 +107,8 @@ class LL_COMMON_API LLThreadSafeRefCount
 	void unref()
 	{
 		llassert(mRef >= 1);
-		if ((--mRef) == 0)		// See note in llapr.h on atomic decrement operator return value.  
-		{	
+		if ((--mRef) == 0)
+		{
 			// If we hit zero, the caller should be the only smart pointer owning the object and we can delete it.
 			// It is technically possible for a vanilla pointer to mess this up, or another thread to
 			// jump in, find this object, create another smart pointer and end up dangling, but if
@@ -124,7 +124,7 @@ class LL_COMMON_API LLThreadSafeRefCount
 	}
 
 private: 
-	LLAtomic32< S32	> mRef; 
+	LLAtomicS32 mRef; 
 };
 
 /**
diff --git a/indra/llcommon/llworkerthread.h b/indra/llcommon/llworkerthread.h
index 09776816a87f2312f8b26a4239d2af944daa2b91..b1a6f613607c908e505a316dbbd5df8bce5abb31 100644
--- a/indra/llcommon/llworkerthread.h
+++ b/indra/llcommon/llworkerthread.h
@@ -33,7 +33,7 @@
 #include <string>
 
 #include "llqueuedthread.h"
-#include "llapr.h"
+#include "llatomic.h"
 
 #define USE_FRAME_CALLBACK_MANAGER 0
 
diff --git a/indra/llcorehttp/_httpservice.h b/indra/llcorehttp/_httpservice.h
index ac518a5de7405022ee270ac6a16b81586b13a56a..d0c37ac1956a9a89b3268b0fc584dfd0eabb323c 100644
--- a/indra/llcorehttp/_httpservice.h
+++ b/indra/llcorehttp/_httpservice.h
@@ -31,7 +31,7 @@
 #include <vector>
 
 #include "linden_common.h"
-#include "llapr.h"
+#include "llatomic.h"
 #include "httpcommon.h"
 #include "httprequest.h"
 #include "_httppolicyglobal.h"
diff --git a/indra/llcorehttp/_refcounted.h b/indra/llcorehttp/_refcounted.h
index 7f713f229836a7c2f34ba6ba01a42b850ad315f6..5cc8914395dc84e4ef4a04d254b6e0df5f2b7cfa 100644
--- a/indra/llcorehttp/_refcounted.h
+++ b/indra/llcorehttp/_refcounted.h
@@ -34,7 +34,7 @@
 #include <boost/thread.hpp>
 #include <boost/intrusive_ptr.hpp>
 
-#include "llapr.h"
+#include "llatomic.h"
 
 
 namespace LLCoreInt
diff --git a/indra/llcorehttp/_thread.h b/indra/llcorehttp/_thread.h
index e058d660e5654700debfe9de6a31f6bcac6f12ff..22b7750badb1b88b64f0ae500f208f3c54ae3199 100644
--- a/indra/llcorehttp/_thread.h
+++ b/indra/llcorehttp/_thread.h
@@ -33,6 +33,7 @@
 #include <boost/function.hpp>
 #include <boost/date_time/posix_time/posix_time_types.hpp>
 
+#include "apr.h" // thread-related functions
 #include "_refcounted.h"
 
 namespace LLCoreInt
diff --git a/indra/llcrashlogger/llcrashlock.cpp b/indra/llcrashlogger/llcrashlock.cpp
index 77abfbcf0f7b1b40f34739e08e72685d23e59dfd..18d164abde5627b2f8a6e6b4447e0ba03e4f39ea 100644
--- a/indra/llcrashlogger/llcrashlock.cpp
+++ b/indra/llcrashlogger/llcrashlock.cpp
@@ -27,6 +27,7 @@
 
 #include "linden_common.h"
 
+#include "llapr.h" // thread-related functions
 #include "llcrashlock.h"
 #include "lldir.h"
 #include "llsd.h"
diff --git a/indra/llmessage/llproxy.h b/indra/llmessage/llproxy.h
index 688dff7c8320916b9f2027f91f16d0cd6408867f..87891901ad6935cc627e63f02d03bf22b010de2f 100644
--- a/indra/llmessage/llproxy.h
+++ b/indra/llmessage/llproxy.h
@@ -298,7 +298,7 @@ class LLProxy: public LLSingleton<LLProxy>
 private:
 	// Is the HTTP proxy enabled? Safe to read in any thread, but do not write directly.
 	// Instead use enableHTTPProxy() and disableHTTPProxy() instead.
-	mutable LLAtomic32<bool> mHTTPProxyEnabled;
+	mutable LLAtomicBool mHTTPProxyEnabled;
 
 	// Mutex to protect shared members in non-main thread calls to applyProxySettings().
 	mutable LLMutex mProxyMutex;
diff --git a/indra/llvfs/llpidlock.cpp b/indra/llvfs/llpidlock.cpp
index 6572edead398f250e6ac45308dc9a3ed3ee8399b..f770e93d45aa678e286d55e2ecef24cbcbd10e65 100644
--- a/indra/llvfs/llpidlock.cpp
+++ b/indra/llvfs/llpidlock.cpp
@@ -27,6 +27,7 @@
 
 #include "linden_common.h"
 
+#include "llapr.h" // thread-related functions
 #include "llpidlock.h"
 #include "lldir.h"
 #include "llsd.h"
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index e607b4a994faa4273e39b3f446e0dab58f21aafa..788fe6a19b0eacfce2a004f3a2a26083fa320936 100644
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -43,6 +43,7 @@
 #define LL_LLAPPVIEWER_H
 
 #include "llallocator.h"
+#include "llapr.h"
 #include "llcontrol.h"
 #include "llsys.h"			// for LLOSInfo
 #include "lltimer.h"
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index a6002bd57f120e74c34dc730ff4262af6f4c3cd1..2e7141bcfc058fee87ac38a446b9208dd95d9ad3 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -26,10 +26,11 @@
 
 #include "llviewerprecompiledheaders.h"
 
+#include "llapr.h"
+#include "apr_portable.h"
 #include "apr_pools.h"
 #include "apr_dso.h"
 #include "llhttpconstants.h"
-#include "llapr.h"
 #include "llmeshrepository.h"
 
 #include "llagent.h"
diff --git a/indra/newview/lltexturecache.h b/indra/newview/lltexturecache.h
index 987b9375c04982132563524ccf670cf8686ba7b7..81ea7aeee2d98057c70f25b486bfc45b95af1d5e 100644
--- a/indra/newview/lltexturecache.h
+++ b/indra/newview/lltexturecache.h
@@ -221,7 +221,7 @@ class LLTextureCache : public LLWorkerThread
 	typedef std::map<LLUUID,S32> size_map_t;
 	size_map_t mTexturesSizeMap;
 	S64 mTexturesSizeTotal;
-	LLAtomic32<BOOL> mDoPurge;
+	LLAtomicBool mDoPurge;
 
 	typedef std::map<S32, Entry> idx_entry_map_t;
 	idx_entry_map_t mUpdatedEntryMap;