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;
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 {
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
264 };
265
266
286 using payload_unique_ptr = std::unique_ptr<T, DeletePayload>;
287
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
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
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 =
427
428
434 void erase (const key_query_type& key,
435 const typename Updater_t::Context_t& ctx =
437
438
454 int extendLastRange (const RANGE& newRange,
455 const typename Updater_t::Context_t& ctx =
457
458
469 void updateRanges (std::function<void (RANGE&)> rangeUpdater,
470 const typename Updater_t::Context_t& ctx =
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 =
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
614 int extendImpl (lock_t& lock,
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.
static const Context_t & defaultContext()
Return the current event context.
EventContext Context_t
Execution context type.
Definition RCUUpdater.h:42
Impl(size_t capacity=10)
Constructor.
value_type * data()
Return a pointer to the start of the data vector.
std::vector< value_type > m_data
Vector holding the map data.
size_t capacity() const
Return the size of the current data vector.
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.
void clear()
Remove all entries in the container.
void quiescent(const typename Updater_t::Context_t &ctx=Updater_t::defaultContext())
Called when this thread is no longer referencing anything from this container.
size_t maxSize() const
Return the maximum size of the map.
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.
size_t trim(const std::vector< key_query_type > &keys, bool trimall=false)
Remove unused entries from the front of the list.
void updatePointers(value_type *new_begin, value_type *new_end)
Consistently update both the begin and last pointers.
bool empty() const
Test if the map is empty.
const_iterator getBegin(const_iterator &last) const
Return the begin/last pointers.
IPayloadDeleter & deleter()
Return a reference to the payload deleter object.
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.
EmplaceResult emplace(const RANGE &range, payload_unique_ptr ptr, bool tryExtend=false, const typename Updater_t::Context_t &ctx=Updater_t::defaultContext())
Add a new element to the map.
const_iterator find(const key_query_type &key) const
Search for the first item less than or equal to KEY.
void delete_function(const T *)
Function to delete a T*.
void erase(const key_query_type &key, const typename Updater_t::Context_t &ctx=Updater_t::defaultContext())
Erase the first item less than or equal to KEY.
void updateRanges(std::function< void(RANGE &)> rangeUpdater, const typename Updater_t::Context_t &ctx=Updater_t::defaultContext())
Update all range objects.
const IPayloadDeleter & deleter() const
Return a reference to the payload deleter object.
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.
CxxUtils::IRangeMapPayloadDeleter< void, typename Updater_t::Context_t > IPayloadDeleter
bool anyInRange(const key_type &r, const std::vector< key_query_type > &keys) const
Test to see if any keys within keys match r.
ConcurrentRangeMap(Updater_t &&updater, std::shared_ptr< IPayloadDeleter > payloadDeleter, size_t capacity=16, const COMPARE &compare=COMPARE())
Constructor.
size_t size() const
Return the current number of elements in the map.
size_t nInserts() const
Return the number times an item was inserted into the map.
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.
Concept for comparison template argument.
Concept check for Updater class used by concurrent classes.
Definition IsUpdater.h:51
int r
Definition globals.cxx:22
Emit stall instruction for use in a spin loop.
delete_function * m_delete
The deletion function.
DeletePayload(const std::default_delete< U > &)
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.