Ion
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
once.h
Go to the documentation of this file.
1 
18 #ifndef ION_BASE_ONCE_H_
19 #define ION_BASE_ONCE_H_
20 
21 #include <functional>
22 
23 #include "base/integral_types.h"
24 #include "base/macros.h"
26 #include "ion/port/atomic.h"
27 #include "ion/port/macros.h"
28 #include "ion/port/threadutils.h"
29 
30 namespace ion {
31 namespace base {
32 
38 class ION_API OnceFlag {
39  public:
40  OnceFlag() : value_(init_value_) {}
41 
47  void CallOnce(const std::function<void()>& target);
48 
49  static void CallChecked(const std::function<bool()>& target) {
50  if (!target()) {
51  LOG(ERROR) << "CallOnce target returned false.";
52  }
53  }
54 
55  private:
56  std::atomic<int32> value_;
57  static const int32 init_value_ = 0;
58  DISALLOW_COPY_AND_ASSIGN(OnceFlag);
59 };
60 
65 template <typename T> class Lazy {
66  public:
67  explicit Lazy(const std::function<T()>& creator) : creator_(creator) {}
68 
70  Lazy(const Lazy<T>& other) : creator_(other.creator_) {}
71  const T& Get() const {
72  flag_.CallOnce(std::bind(&Lazy::Populate, this));
73  return value_;
74  }
75 
76  private:
77  void Populate() const { value_ = creator_(); }
78 
80  std::function<T()> creator_;
81 
84  mutable T value_;
85 
88  mutable OnceFlag flag_;
89  ION_DISALLOW_ASSIGN_ONLY(Lazy<T>);
90 };
91 
93 
94 inline void OnceFlag::CallOnce(const std::function<void()>& target) {
97  const int32 running_value = 0x325ad493;
98  const int32 done_value = 0x46f36511;
101  if (value_.load(std::memory_order_acquire) == done_value) {
102  return;
103  }
104  int32 expected_value = init_value_;
105  if (value_.compare_exchange_strong(expected_value, running_value)) {
106  target();
110  value_ = done_value;
111  } else if (expected_value != done_value) {
117  while (value_ != done_value) {
119  }
120  }
121 }
122 
123 } // namespace base
124 } // namespace ion
125 
128 #define ION_STATIC_ONCE_CHECKED(function) \
129  ION_STATIC_ONCE(std::bind(::ion::base::OnceFlag::CallChecked, &function));
130 
133 #define ION_STATIC_ONCE(function) \
134  do { \
135  ION_DECLARE_SAFE_STATIC_POINTER(::ion::base::OnceFlag, s_once_flag_macro); \
136  s_once_flag_macro->CallOnce(function); \
137  } while (0)
138 
139 #endif // ION_BASE_ONCE_H_
Lazy(const Lazy< T > &other)
Copy constructor, only copies the creator.
Definition: once.h:70
static void CallChecked(const std::function< bool()> &target)
Definition: once.h:49
Lazily populates a value.
Definition: once.h:65
#define LOG(severity)
Logs the streamed message unconditionally with a severity of severity.
Definition: logging.h:216
void YieldThread()
Causes the calling thread to relinquish the CPU if there are other threads waiting to execute...
Definition: threadutils.cc:359
Lazy(const std::function< T()> &creator)
Definition: once.h:67
const T & Get() const
Definition: once.h:71
OnceFlag ensures that a target function is only evaluated once.
Definition: once.h:38
void CallOnce(const std::function< void()> &target)
If this OnceFlag instance has never executed a target function, CallOnce calls the target function...
Definition: once.h:94