blob: b00ccdac0e0010986825c18ae474c44b02773387 [file] [log] [blame]
Brian Silvermanf7bd1c22015-12-24 16:07:11 -08001/*----------------------------------------------------------------------------*/
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_