ATLAS Offline Software
Loading...
Searching...
No Matches
ConcurrentRangeMap.h
Go to the documentation of this file.
1// This file's extension implies that it's C, but it's really -*- C++ -*-.
2/*
3 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
4*/
11
12
13#ifndef CXXUTILS_CONCURRENTRANGEMAP_H
14#define CXXUTILS_CONCURRENTRANGEMAP_H
15
16
17#include "CxxUtils/stall.h"
18#include "CxxUtils/IsUpdater.h"
19#include <atomic>
20#include <mutex>
21#include <utility>
22#include <vector>
23#include <memory>
24#include <algorithm>
25#include <functional>
26#include <ranges>
27
28
29namespace CxxUtils {
30
31
42template <class T, class CONTEXT>
44{
45public:
47 typedef void delete_function (const T*);
48
49
55
56
58 virtual ~IRangeMapPayloadDeleter() = default;
59
60
68 virtual void discard (const T* p) = 0;
69
70
75 virtual void quiescent (const CONTEXT& ctx) = 0;
76
77
82
83
84private:
87};
88
89
90//*****************************************************************************
91
92
93namespace detail {
94
95
100template <class COMPARE, class RANGE, class KEY, class CONTEXT>
101concept IsConcurrentRangeCompare = requires (const COMPARE& c,
102 const RANGE& r1,
103 const RANGE& r2,
104 RANGE& r_nc,
105 const KEY& k,
106 const CONTEXT& ctx)
107{
108 { c(k, r2) } -> std::same_as<bool>;
109 { c(r1, r2) } -> std::same_as<bool>;
110 { c.inRange (k, r2) } -> std::same_as<bool>;
111 { c.overlap (ctx, r1, r_nc) } -> std::same_as<int>;
112 { c.extendRange (r_nc, r2) } -> std::same_as<int>;
113};
114
115
116} // namespace detail
117
118
119//*****************************************************************************
120
121
208template <class RANGE, class KEY, class T, class COMPARE,
209 template <class> class UPDATER>
213{
214public:
215 typedef RANGE key_type;
216 typedef const T* mapped_type;
217 typedef std::pair<RANGE, const T*> value_type;
218 typedef const value_type& const_reference;
219 typedef const value_type* const_pointer;
220 typedef size_t size_type;
221 typedef int difference_type;
222 typedef COMPARE key_compare;
223 typedef KEY key_query_type;
224
225
227 typedef void delete_function (const T*);
228
229
237 {
239 DeletePayload (delete_function* delfcn)
240 : m_delete (delfcn)
241 {
242 }
243
245 template <class U>
246 static void delfcn (const T* p)
247 {
248 delete reinterpret_cast<const U*>(p);
249 }
250 template <class U>
251 DeletePayload (const std::default_delete<U>&)
252 {
254 }
255
257 void operator() (const T* p) const
258 {
259 m_delete (p);
260 }
261
263 delete_function* m_delete;
264 };
265
266
286 using payload_unique_ptr = std::unique_ptr<T, DeletePayload>;
287
288 using const_iterator = const value_type*;
289 using const_iterator_range = std::ranges::subrange<const_iterator>;
290
291
302 class Impl
303 {
304 public:
309 Impl (size_t capacity = 10);
310
311
315 ~Impl() = default;
316
317
321 value_type* data();
322
323
327 size_t capacity() const;
328
329
330 private:
332 std::vector<value_type> m_data;
333 };
334
335 using Updater_t = UPDATER<Impl>;
337
338
349 std::shared_ptr<IPayloadDeleter> payloadDeleter,
350 size_t capacity = 16,
351 const COMPARE& compare = COMPARE());
352
353
360
361
366
367
371 const IPayloadDeleter& deleter() const;
372
373
379 const_iterator find (const key_query_type& key) const;
380
381
383 enum class EmplaceResult
384 {
387
390
393
394 // Existing range was extended to match the new range; new object
395 // was deleted.
397 };
398
399
424 bool tryExtend = false,
425 const typename Updater_t::Context_t& ctx =
426 Updater_t::defaultContext());
427
428
434 void erase (const key_query_type& key,
435 const typename Updater_t::Context_t& ctx =
436 Updater_t::defaultContext());
437
438
454 int extendLastRange (const RANGE& newRange,
455 const typename Updater_t::Context_t& ctx =
456 Updater_t::defaultContext());
457
458
469 void updateRanges (std::function<void (RANGE&)> rangeUpdater,
470 const typename Updater_t::Context_t& ctx =
471 Updater_t::defaultContext());
472
473
494 size_t trim (const std::vector<key_query_type>& keys, bool trimall = false);
495
496
501 void clear();
502
503
507 size_t size() const;
508
509
513 bool empty() const;
514
515
519 size_t capacity() const;
520
521
525 size_t nInserts() const;
526
527
531 size_t maxSize() const;
532
533
538
539
545 void quiescent (const typename Updater_t::Context_t& ctx =
546 Updater_t::defaultContext());
547
548
549private:
551 typedef std::mutex mutex_t;
552 typedef std::lock_guard<mutex_t> lock_t;
553
554
571
572
578 void updatePointers (value_type* new_begin, value_type* new_end);
579
580
586 bool anyInRange (const key_type& r,
587 const std::vector<key_query_type>& keys) const;
588
589
599 void installImpl (std::unique_ptr<Impl> new_impl,
600 value_type* new_begin,
601 value_type* new_end,
602 const typename Updater_t::Context_t& ctx);
603
604
615 const RANGE& extendedRange,
616 const typename Updater_t::Context_t& ctx);
617
618
619
623
625 COMPARE m_compare;
626
638 std::shared_ptr<IPayloadDeleter> m_payloadDeleter;
639
641 Impl* m_impl;
642
654 std::atomic<value_type*> m_begin;
655 std::atomic<value_type*> m_last;
656
659 size_t m_maxSize;
660
663};
664
665
666} // namespace CxxUtils
667
668
670
671
672#endif // not CXXUTILS_CONCURRENTRANGEMAP_H
Concept check for Updater class used by concurrent classes.
Helper to delete payload objects for ConcurrentRangeMap.
IRangeMapPayloadDeleter(delete_function *delfcn)
Constructor.
virtual void discard(const T *p)=0
Queue an object for deletion.
virtual void quiescent(const CONTEXT &ctx)=0
Mark a slot as quiescent.
void delete_function(const T *)
Type of a function to delete a payload object immediately.
virtual ~IRangeMapPayloadDeleter()=default
Virtual destructor.
Implementation object.
size_t capacity() const
Return the size of the current data vector.
~Impl()=default
Destructor.
Impl(size_t capacity=10)
Constructor.
std::atomic< Block_t > m_data[1]
The set data. The implementation objects are allocated such that there are actually m_nblocks entries...
value_type * data()
Return a pointer to the start of the data vector.
Concept for comparison template argument.
Concept check for Updater class used by concurrent classes.
Definition IsUpdater.h:51
int r
Definition globals.cxx:22
CxxUtils::iterator_range< const_iterator > const_iterator_range
A range defined by two iterators.
const_iterator getBegin(const_iterator &last) const
Return the begin/last pointers.
COMPARE m_compare
Comparison object.
size_t trim(const std::vector< key_query_type > &keys, bool trimall=false)
Remove unused entries from the front of the list.
Updater_t & updater()
Access the Updater instance.
std::mutex mutex_t
Mutex used for synchronization when switching to a new implementation object.
~ConcurrentRangeMap()
Destructor.
void updatePointers(value_type *new_begin, value_type *new_end)
Consistently update both the begin and last pointers.
const_iterator find(bit_t bit) const
If bit bit is set, return an iterator pointing to it.
bool empty() const
Return true if there are no 1 bits in the set.
IPayloadDeleter & deleter()
Return a reference to the payload deleter object.
void quiescent(const Context_t &ctx)
Called when this thread is no longer referencing anything from this container.
bit_t size() const
Count the number of 1 bits in the set.
ConcurrentBitset & erase(bit_t bit)
Turn off one bit.
void installImpl(std::unique_ptr< Impl > new_impl, value_type *new_begin, value_type *new_end, const typename Updater_t::Context_t &ctx)
Install a new implementation instance and make it visible.
int extendImpl(lock_t &lock, const RANGE &extendedRange, const typename Updater_t::Context_t &ctx)
Extend the range of the last entry of the map.
bit_t capacity() const
The number of bits that this container can hold.
const_iterator_range range() const
Return an iterator range covering the entire map.
mutex_t m_mutex
Mutex protecting the container.
std::shared_ptr< IPayloadDeleter > m_payloadDeleter
Payload deleter object. Important: do not discard an object while it's still reachable from the m_beg...
UPDATER< Impl > Updater_t
ConcurrentRangeMap(Updater_t &&updater, std::shared_ptr< IPayloadDeleter > payloadDeleter, size_t capacity=16, const COMPARE &compare=COMPARE())
Constructor.
ConcurrentBitset & clear()
Clear all bits in the set.
EmplaceResult
Results returned from emplace().
@ DUPLICATE
New object duplicates an existing range, and was not added.
@ OVERLAP
New object was added, but overlaps with an existing range.
bool anyInRange(const key_type &r, const std::vector< key_query_type > &keys) const
Test to see if any keys within keys match r.
Updater_t m_updater
Updater object. This maintains ownership of the current implementation class and the older versions.
std::unique_ptr< T, DeletePayload > payload_unique_ptr
unique_ptr holding a payload object.
CxxUtils::IRangeMapPayloadDeleter< T, typename Updater_t::Context_t > IPayloadDeleter
std::lock_guard< mutex_t > lock_t
size_t m_nInserts
Some basic statistics.
std::atomic< Impl * > m_impl
The current implementation object.
std::atomic< value_type * > m_begin
Pointers to the first and last elements of the container. m_last is not the usual end pointer; it poi...
size_t nInserts() const
Return the number times an item was inserted into the map.
size_t maxSize() const
Return the maximum size of the map.
void updateRanges(std::function< void(RANGE &)> rangeUpdater, const typename Updater_t::Context_t &ctx=Updater_t::defaultContext())
Update all range objects.
std::pair< const_iterator, bool > emplace(key_type key, mapped_type val, const Context_t &ctx=Updater_t::defaultContext())
Add an element to the map.
int extendLastRange(const RANGE &newRange, const typename Updater_t::Context_t &ctx=Updater_t::defaultContext())
Extend the range of the last entry of the map.
std::atomic< value_type * > m_last
Lock_t lock()
Take a lock on the container.
Emit stall instruction for use in a spin loop.
void operator()(const T *p) const
Delete a pointer.
DeletePayload(const std::default_delete< U > &)
delete_function * m_delete
The deletion function.
static void delfcn(const T *p)
Allow initializing a payload_unique_ptr from a std::unique_ptr.
DeletePayload(delete_function *delfcn)
Initialize with an explicit deletion function.
Iterator over all 1 bits in the set.