PMDK C++ bindings  1.13.0-git107.g7e59f08f
This is the C++ bindings documentation for PMDK's libpmemobj.
volatile_state.hpp
Go to the documentation of this file.
1 // SPDX-License-Identifier: BSD-3-Clause
2 /* Copyright 2019-2020, Intel Corporation */
3 
11 #ifndef LIBPMEMOBJ_CPP_VOLATILE_STATE_HPP
12 #define LIBPMEMOBJ_CPP_VOLATILE_STATE_HPP
13 
14 #include <cassert>
15 #include <functional>
16 #include <memory>
17 #include <mutex>
18 #include <shared_mutex>
19 #include <tuple>
20 #include <unordered_map>
21 
24 #include <libpmemobj++/pool.hpp>
26 
27 namespace pmem
28 {
29 
30 namespace detail
31 {
32 
39 public:
40  template <typename T>
41  static T *
42  get_if_exists(const PMEMoid &oid)
43  {
44  auto &map = get_map();
45 
46  {
47  std::shared_lock<rwlock_type> lock(get_rwlock());
48  auto it = map.find(oid);
49  if (it != map.end())
50  return static_cast<T *>(it->second.get());
51  else
52  return nullptr;
53  }
54  }
55 
56  template <typename T>
57  static T *
58  get(const PMEMoid &oid)
59  {
60  auto &map = get_map();
61 
62  auto element = get_if_exists<T>(oid);
63  if (element)
64  return element;
65 
66  if (pmemobj_tx_stage() != TX_STAGE_NONE)
68  "volatile_state::get() cannot be called in a transaction");
69 
70  {
71  std::unique_lock<rwlock_type> lock(get_rwlock());
72 
73  auto deleter = [](void const *data) {
74  T const *p = static_cast<T const *>(data);
75  delete p;
76  };
77 
78  auto it = map.find(oid);
79  if (it == map.end()) {
80  auto ret = map.emplace(
81  std::piecewise_construct,
82  std::forward_as_tuple(oid),
83  std::forward_as_tuple(new T, deleter));
84 
85  /* emplace could fail only if there is already
86  * an element with the same key which is not
87  * possible */
88  assert(ret.second);
89 
90  it = ret.first;
91 
92  auto pop = pmemobj_pool_by_oid(oid);
93  auto *user_data =
94  static_cast<detail::pool_data *>(
95  pmemobj_get_user_data(pop));
96 
97  user_data->set_cleanup([oid] {
98  clear_from_pool(oid.pool_uuid_lo);
99  });
100  }
101 
102  return static_cast<T *>(it->second.get());
103  }
104  }
105 
106  static void
107  destroy(const PMEMoid &oid)
108  {
109  if (pmemobj_tx_stage() == TX_STAGE_WORK) {
111  obj::flat_transaction::stage::oncommit, [oid] {
112  std::unique_lock<rwlock_type> lock(
113  get_rwlock());
114  get_map().erase(oid);
115  });
116  } else {
117  std::unique_lock<rwlock_type> lock(get_rwlock());
118  get_map().erase(oid);
119  }
120  }
121 
122 private:
123  struct pmemoid_hash {
124  std::size_t
125  operator()(const PMEMoid &oid) const
126  {
127  return oid.pool_uuid_lo + oid.off;
128  }
129  };
130 
131  struct pmemoid_equal_to {
132  bool
133  operator()(const PMEMoid &lhs, const PMEMoid &rhs) const
134  {
135  return lhs.pool_uuid_lo == rhs.pool_uuid_lo &&
136  lhs.off == rhs.off;
137  }
138  };
139 
140  using key_type = PMEMoid;
141  using value_type =
142  std::unique_ptr<void,
143  std::add_pointer<void(const void *)>::type>;
144 
145  using map_type = std::unordered_map<key_type, value_type, pmemoid_hash,
146  pmemoid_equal_to>;
147 
148  using rwlock_type = std::shared_timed_mutex;
149 
150  static void
151  clear_from_pool(uint64_t pool_id)
152  {
153  std::unique_lock<rwlock_type> lock(get_rwlock());
154  auto &map = get_map();
155 
156  for (auto it = map.begin(); it != map.end();) {
157  if (it->first.pool_uuid_lo == pool_id)
158  it = map.erase(it);
159  else
160  ++it;
161  }
162  }
163 
164  static map_type &
165  get_map()
166  {
167  static map_type map;
168  return map;
169  }
170 
171  static rwlock_type &
172  get_rwlock()
173  {
174  static rwlock_type rwlock;
175  return rwlock;
176  }
177 };
178 
179 } /* namespace detail */
180 
181 } /* namespace pmem */
182 
183 #endif /* LIBPMEMOBJ_CPP_VOLATILE_STATE_HPP */
static void register_callback(stage stg, std::function< void()> cb)
Registers callback to be called on specified stage for the transaction.
Definition: transaction.hpp:487
Global key value store which allows persistent objects to use volatile memory.
Definition: volatile_state.hpp:38
Custom transaction error class.
Definition: pexceptions.hpp:167
Commonly used functionality.
Functions for lifetime management.
Persistent memory namespace.
Definition: allocation_flag.hpp:15
C++ pmemobj pool.
C++ pmemobj transactions.