TARAXA
lazy.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #include <cassert>
4 #include <functional>
5 #include <mutex>
6 #include <type_traits>
7 
8 namespace taraxa::util::lazy {
9 using std::enable_if_t;
10 using std::function;
11 using std::is_invocable_v;
12 using std::mutex;
13 using std::remove_reference;
14 using std::size_t;
15 using std::unique_lock;
16 
17 // TODO [1657]: clean up this class - remove ned/delete, ideally remove whole Lazy class !!!
18 template <typename Provider>
19 class Lazy {
20  Provider* provider_ = nullptr;
21 
22  public:
23  using val_t = typename remove_reference<decltype((*provider_)())>::type;
24 
25  private:
26  val_t* val_ptr_ = nullptr;
27  mutex mu_;
28  bool initializing_ = false;
29 
30  public:
31  Lazy(Provider const& provider) : provider_(new Provider(provider)) {}
32  Lazy(Provider&& provider) : provider_(new Provider(provider)) {}
33  ~Lazy() {
34  if (provider_) {
35  delete provider_;
36  }
37  if (val_ptr_) {
38  delete val_ptr_;
39  }
40  }
41 
42  val_t* get() {
43  if (val_ptr_) {
44  return val_ptr_;
45  }
46  unique_lock l(mu_);
47  if (val_ptr_) {
48  return val_ptr_;
49  }
50  // this will persist any error that happened during initialization
51  assert(!initializing_);
52  initializing_ = true;
53  val_ptr_ = new val_t((*provider_)());
54  delete provider_;
55  provider_ = nullptr;
56  initializing_ = false;
57  return val_ptr_;
58  }
59 
60  val_t const* get() const { return const_cast<val_t const*>(const_cast<Lazy*>(this)->get()); }
61 
62  val_t* operator->() { return get(); }
63  val_t const* operator->() const { return get(); }
64 
65  val_t& operator*() { return *operator->(); }
66  val_t const& operator*() const { return *operator->(); }
67 
68  // clang-format off
69  operator val_t&() { return operator*(); }
70  operator val_t const &() const { return operator*(); }
71  // clang-format on
72 
73  template <typename T>
74  auto& operator[](T t) {
75  return operator*()[t];
76  }
77 
78  template <typename T>
79  auto const& operator[](T t) const {
80  return operator*()[t];
81  }
82 
83  template <typename T>
84  auto& operator=(T t) {
85  return operator*() = t;
86  }
87 };
88 
89 template <typename T>
90 using LazyVal = Lazy<function<T()>>;
91 
92 } // namespace taraxa::util::lazy
Definition: lazy.hpp:19
auto const & operator[](T t) const
Definition: lazy.hpp:79
~Lazy()
Definition: lazy.hpp:33
val_t * get()
Definition: lazy.hpp:42
mutex mu_
Definition: lazy.hpp:27
auto & operator=(T t)
Definition: lazy.hpp:84
Provider * provider_
Definition: lazy.hpp:20
Lazy(Provider const &provider)
Definition: lazy.hpp:31
val_t * operator->()
Definition: lazy.hpp:62
val_t & operator*()
Definition: lazy.hpp:65
val_t const & operator*() const
Definition: lazy.hpp:66
val_t const * get() const
Definition: lazy.hpp:60
val_t * val_ptr_
Definition: lazy.hpp:26
Lazy(Provider &&provider)
Definition: lazy.hpp:32
auto & operator[](T t)
Definition: lazy.hpp:74
typename remove_reference< decltype((*provider_)())>::type val_t
Definition: lazy.hpp:23
bool initializing_
Definition: lazy.hpp:28
val_t const * operator->() const
Definition: lazy.hpp:63
Definition: lazy.hpp:8