Squashed 'third_party/ntcore_2016/' content from commit d8de5e4
Change-Id: Id4839f41b6a620d8bae58dcf1710016671cc4992
git-subtree-dir: third_party/ntcore_2016
git-subtree-split: d8de5e4f19e612e7102172c0dbf152ce82d3d63a
diff --git a/src/atomic_static.h b/src/atomic_static.h
new file mode 100644
index 0000000..b00ccda
--- /dev/null
+++ b/src/atomic_static.h
@@ -0,0 +1,49 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2015. All Rights Reserved. */
+/* Open Source Software - may be modified and shared by FRC teams. The code */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project. */
+/*----------------------------------------------------------------------------*/
+
+#ifndef NT_ATOMIC_STATIC_H_
+#define NT_ATOMIC_STATIC_H_
+
+#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
+
+// Just use a local static. This is thread-safe per
+// http://preshing.com/20130930/double-checked-locking-is-fixed-in-cpp11/
+
+// Per https://msdn.microsoft.com/en-us/library/Hh567368.aspx "Magic Statics"
+// are supported in Visual Studio 2015 but not in earlier versions.
+#define ATOMIC_STATIC(cls, inst) static cls inst
+#define ATOMIC_STATIC_DECL(cls)
+#define ATOMIC_STATIC_INIT(cls)
+
+#else
+// From http://preshing.com/20130930/double-checked-locking-is-fixed-in-cpp11/
+#include <atomic>
+#include <mutex>
+
+#define ATOMIC_STATIC(cls, inst) \
+ cls* inst##tmp = m_instance.load(std::memory_order_acquire); \
+ if (inst##tmp == nullptr) { \
+ std::lock_guard<std::mutex> lock(m_instance_mutex); \
+ inst##tmp = m_instance.load(std::memory_order_relaxed); \
+ if (inst##tmp == nullptr) { \
+ inst##tmp = new cls; \
+ m_instance.store(inst##tmp, std::memory_order_release); \
+ } \
+ } \
+ cls& inst = *inst##tmp
+
+#define ATOMIC_STATIC_DECL(cls) \
+ static std::atomic<cls*> m_instance; \
+ static std::mutex m_instance_mutex;
+
+#define ATOMIC_STATIC_INIT(cls) \
+ std::atomic<cls*> cls::m_instance; \
+ std::mutex cls::m_instance_mutex;
+
+#endif
+
+#endif // NT_ATOMIC_STATIC_H_