9 #ifndef LIBPMEMOBJ_CPP_ENUMERABLE_THREAD_SPECIFIC_HPP
10 #define LIBPMEMOBJ_CPP_ENUMERABLE_THREAD_SPECIFIC_HPP
22 #include <unordered_map>
45 static constexpr
size_t initial_queue_capacity = 1024;
48 std::size_t queue_capacity;
49 std::deque<size_t> queue;
91 using storage_type = Storage;
92 using mutex_type = Mutex;
97 using size_type =
typename storage_type::size_type;
98 using difference_type =
typename storage_type::difference_type;
99 using reference = value_type &;
100 using const_reference =
const value_type &;
101 using pointer = value_type *;
102 using const_pointer =
const value_type *;
103 using iterator =
typename storage_type::iterator;
104 using const_iterator =
typename storage_type::const_iterator;
107 template <
typename Handler>
126 const_iterator
end()
const;
131 void set_cached_size(
size_t s);
132 size_t get_cached_size();
137 obj::p<std::atomic<
size_t>> _storage_size;
141 : queue_capacity(initial_queue_capacity), queue(initial_queue_capacity, 0)
144 std::iota(queue.begin(), queue.end(), 0);
155 std::unique_lock<std::mutex> lock(mutex);
158 queue.push_front(queue_capacity++);
160 auto front = queue.front();
174 std::unique_lock<std::mutex> lock(mutex);
176 queue.push_front(
id);
183 thread_id_type::get_id_manager()
196 auto &manager = get_id_manager();
202 #if LIBPMEMOBJ_CPP_VG_DRD_ENABLED
203 ANNOTATE_BENIGN_RACE_SIZED(
204 &manager,
sizeof(std::mutex),
205 "https://bugs.kde.org/show_bug.cgi?id=416286");
218 get_id_manager().release(
id);
233 template <
typename T,
typename Mutex,
typename Storage>
236 _storage_size.
get_rw() = 0;
242 template <
typename T,
typename Mutex,
typename Storage>
246 auto pop = get_pool();
249 #if LIBPMEMOBJ_CPP_VG_HELGRIND_ENABLED
250 VALGRIND_HG_DISABLE_CHECKING(&_storage_size,
sizeof(_storage_size));
253 #if LIBPMEMOBJ_CPP_VG_HELGRIND_ENABLED || LIBPMEMOBJ_CPP_VG_DRD_ENABLED
254 ANNOTATE_HAPPENS_BEFORE(&_storage_size);
257 _storage_size.
get_rw().store(s);
258 pop.persist(_storage_size);
264 template <
typename T,
typename Mutex,
typename Storage>
266 enumerable_thread_specific<T, Mutex, Storage>::get_cached_size()
268 auto s = _storage_size.
get_ro().load();
270 #if LIBPMEMOBJ_CPP_VG_HELGRIND_ENABLED || LIBPMEMOBJ_CPP_VG_DRD_ENABLED
271 ANNOTATE_HAPPENS_AFTER(&_storage_size);
284 template <
typename T,
typename Mutex,
typename Storage>
285 template <
typename Handler>
289 for (reference e : *
this) {
303 template <
typename T,
typename Mutex,
typename Storage>
304 typename enumerable_thread_specific<T, Mutex, Storage>::reference
307 assert(pmemobj_tx_stage() != TX_STAGE_WORK);
310 auto index = tid.
get();
312 auto cached_size = get_cached_size();
314 if (index >= cached_size) {
315 std::unique_lock<mutex_type> lock(_mutex);
319 auto size = _storage.size();
322 _storage.resize(index + 1);
323 set_cached_size(index + 1);
324 }
else if (
size != cached_size) {
325 set_cached_size(
size);
334 return _storage[index];
343 template <
typename T,
typename Mutex,
typename Storage>
347 auto pop = get_pool();
350 _storage_size.
get_rw() = 0;
360 template <
typename T,
typename Mutex,
typename Storage>
361 typename enumerable_thread_specific<T, Mutex, Storage>::size_type
364 return _storage.size();
372 template <
typename T,
typename Mutex,
typename Storage>
376 return _storage.size() == 0;
384 template <
typename T,
typename Mutex,
typename Storage>
385 typename enumerable_thread_specific<T, Mutex, Storage>::iterator
388 return _storage.begin();
396 template <
typename T,
typename Mutex,
typename Storage>
397 typename enumerable_thread_specific<T, Mutex, Storage>::iterator
400 return _storage.end();
408 template <
typename T,
typename Mutex,
typename Storage>
409 typename enumerable_thread_specific<T, Mutex, Storage>::const_iterator
412 return _storage.begin();
420 template <
typename T,
typename Mutex,
typename Storage>
421 typename enumerable_thread_specific<T, Mutex, Storage>::const_iterator
424 return _storage.end();
434 template <
typename T,
typename Mutex,
typename Storage>
438 auto pop = pmemobj_pool_by_ptr(
this);
439 assert(pop !=
nullptr);
Class for storing thread local data.
Definition: enumerable_thread_specific.hpp:90
const_iterator end() const
Returns an const_iterator to element after the last.
Definition: enumerable_thread_specific.hpp:422
iterator end()
Returns an iterator to element after the last.
Definition: enumerable_thread_specific.hpp:398
void initialize(Handler handler=[](reference) {})
Initialization method.
Definition: enumerable_thread_specific.hpp:287
enumerable_thread_specific()
Constructor.
Definition: enumerable_thread_specific.hpp:234
size_type size() const
Returns number of elements being stored in the container.
Definition: enumerable_thread_specific.hpp:362
const_iterator begin() const
Returns an const_iterator to the beginning.
Definition: enumerable_thread_specific.hpp:410
bool empty() const
Determines if container is empty or not.
Definition: enumerable_thread_specific.hpp:374
void clear()
Removes all elements from the container.
Definition: enumerable_thread_specific.hpp:345
iterator begin()
Returns an iterator to the beginning.
Definition: enumerable_thread_specific.hpp:386
reference local()
Returns data reference for the current thread.
Definition: enumerable_thread_specific.hpp:305
static void run(obj::pool_base &pool, std::function< void()> tx, Locks &... locks)
Execute a closure-like transaction and lock locks.
Definition: transaction.hpp:810
T & get_rw()
Retrieves read-write reference of the object.
Definition: p.hpp:114
const T & get_ro() const noexcept
Retrieves read-only const reference of the object.
Definition: p.hpp:129
The non-template pool base class.
Definition: pool.hpp:51
Persistent version of segment vector with std::vector compatible interface.
Definition: segment_vector.hpp:506
Persistent memory resident shared_mutex implementation.
Definition: shared_mutex.hpp:32
Commonly used functionality.
Persistent memory namespace.
Definition: allocation_flag.hpp:15
A persistent version of segment vector implementation.
Pmem-resident shared mutex.
This structure is used for assigning unique thread ids so that those ids will be reused in case of th...
Definition: enumerable_thread_specific.hpp:35
void release(size_t id)
Releases thread id so that it can be reused by other threads.
Definition: enumerable_thread_specific.hpp:172
size_t get()
Obtain unique thread id.
Definition: enumerable_thread_specific.hpp:153
RAII-style structure for holding thread id.
Definition: enumerable_thread_specific.hpp:53
~thread_id_type()
thread_id_type destructor.
Definition: enumerable_thread_specific.hpp:216
size_t get()
Obtain current thread id.
Definition: enumerable_thread_specific.hpp:225
thread_id_type()
thread_id_type constructor.
Definition: enumerable_thread_specific.hpp:194