WPILibC++  unspecified
atomic_static.h
1 /*----------------------------------------------------------------------------*/
2 /* Copyright (c) 2015-2018 FIRST. 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 WPIUTIL_SUPPORT_ATOMIC_STATIC_H_
9 #define WPIUTIL_SUPPORT_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 // WPIUTIL_SUPPORT_ATOMIC_STATIC_H_