Brian Silverman | f7bd1c2 | 2015-12-24 16:07:11 -0800 | [diff] [blame^] | 1 | /*----------------------------------------------------------------------------*/ |
| 2 | /* Copyright (c) FIRST 2015. All Rights Reserved. */ |
| 3 | /* Open Source Software - may be modified and shared by FRC teams. The code */ |
| 4 | /* must be accompanied by the FIRST BSD license file in the root directory of */ |
| 5 | /* the project. */ |
| 6 | /*----------------------------------------------------------------------------*/ |
| 7 | |
| 8 | #ifndef NT_ATOMIC_STATIC_H_ |
| 9 | #define NT_ATOMIC_STATIC_H_ |
| 10 | |
| 11 | #if !defined(_MSC_VER) || (_MSC_VER >= 1900) |
| 12 | |
| 13 | // Just use a local static. This is thread-safe per |
| 14 | // http://preshing.com/20130930/double-checked-locking-is-fixed-in-cpp11/ |
| 15 | |
| 16 | // Per https://msdn.microsoft.com/en-us/library/Hh567368.aspx "Magic Statics" |
| 17 | // are supported in Visual Studio 2015 but not in earlier versions. |
| 18 | #define ATOMIC_STATIC(cls, inst) static cls inst |
| 19 | #define ATOMIC_STATIC_DECL(cls) |
| 20 | #define ATOMIC_STATIC_INIT(cls) |
| 21 | |
| 22 | #else |
| 23 | // From http://preshing.com/20130930/double-checked-locking-is-fixed-in-cpp11/ |
| 24 | #include <atomic> |
| 25 | #include <mutex> |
| 26 | |
| 27 | #define ATOMIC_STATIC(cls, inst) \ |
| 28 | cls* inst##tmp = m_instance.load(std::memory_order_acquire); \ |
| 29 | if (inst##tmp == nullptr) { \ |
| 30 | std::lock_guard<std::mutex> lock(m_instance_mutex); \ |
| 31 | inst##tmp = m_instance.load(std::memory_order_relaxed); \ |
| 32 | if (inst##tmp == nullptr) { \ |
| 33 | inst##tmp = new cls; \ |
| 34 | m_instance.store(inst##tmp, std::memory_order_release); \ |
| 35 | } \ |
| 36 | } \ |
| 37 | cls& inst = *inst##tmp |
| 38 | |
| 39 | #define ATOMIC_STATIC_DECL(cls) \ |
| 40 | static std::atomic<cls*> m_instance; \ |
| 41 | static std::mutex m_instance_mutex; |
| 42 | |
| 43 | #define ATOMIC_STATIC_INIT(cls) \ |
| 44 | std::atomic<cls*> cls::m_instance; \ |
| 45 | std::mutex cls::m_instance_mutex; |
| 46 | |
| 47 | #endif |
| 48 | |
| 49 | #endif // NT_ATOMIC_STATIC_H_ |