XRootD
XrdPfcStableChunkVector.hh
Go to the documentation of this file.
1 #ifndef __XRDPFC_STABLECHUNKVECTOR_HH__
2 #define __XRDPFC_STABLECHUNKVECTOR_HH__
3 
4 #include <cstddef>
5 #include <limits>
6 #include <vector>
7 
8 namespace XrdPfc {
9 
10 //==============================================================================
11 // StableChunkVector
12 //==============================================================================
13 
19 
20 template<typename T, unsigned InnerShift = 12, unsigned MaxChunks = 1024>
22 {
23 public:
24  static constexpr std::size_t s_chunk_size = std::size_t(1) << InnerShift;
25  static constexpr std::size_t s_chunk_mask = s_chunk_size - 1;
26  static constexpr std::size_t s_capacity = std::size_t(MaxChunks) * s_chunk_size;
27 
28  // Token ids are ints.
29  static_assert(s_capacity <= (std::size_t) std::numeric_limits<int>::max(),
30  "StableChunkVector: capacity must be representable as int");
31 
32  StableChunkVector() { m_chunks.reserve(MaxChunks); }
33 
34  std::size_t size() const { return m_size; }
35  std::size_t capacity() const { return s_capacity; }
36  bool full() const { return m_size >= s_capacity; }
37 
38  T& operator[](std::size_t i) { return m_chunks[i >> InnerShift][i & s_chunk_mask]; }
39  const T& operator[](std::size_t i) const { return m_chunks[i >> InnerShift][i & s_chunk_mask]; }
40 
42  int add()
43  {
44  if (full())
45  return -1;
46  if (m_chunks.empty() || m_chunks.back().size() == s_chunk_size)
47  {
48  // ! full() keeps this within the reserved outer capacity.
49  m_chunks.emplace_back();
50  m_chunks.back().reserve(s_chunk_size);
51  }
52  m_chunks.back().emplace_back();
53  return (int) m_size++;
54  }
55 
56 private:
57  std::vector<std::vector<T>> m_chunks;
58  std::size_t m_size = 0;
59 };
60 
61 
62 //==============================================================================
63 // StableChunkPool
64 //==============================================================================
65 
69 
70 template<typename T, unsigned InnerShift = 12, unsigned MaxChunks = 1024>
71 class StableChunkPool : public StableChunkVector<T, InnerShift, MaxChunks>
72 {
74 
75 public:
78  int acquire()
79  {
80  if ( ! m_free_slots.empty())
81  {
82  int i = m_free_slots.back();
83  m_free_slots.pop_back();
84  return i;
85  }
86  return Base::add();
87  }
88 
90  void release(int i)
91  {
92  (*this)[i].clear();
93  m_free_slots.push_back(i);
94  }
95 
96  std::size_t n_free() const { return m_free_slots.size(); }
97  std::size_t n_in_use() const { return Base::size() - m_free_slots.size(); }
98 
99 private:
100  // Only touched under the caller's mutex, never referenced.
101  std::vector<int> m_free_slots;
102 };
103 
104 }
105 
106 #endif
void release(int i)
Clear the slot and return it for reuse. Caller must hold its mutex.
const T & operator[](std::size_t i) const
static constexpr std::size_t s_chunk_size
static constexpr std::size_t s_chunk_mask
static constexpr std::size_t s_capacity
int add()
Append a default-constructed T; return its index, or -1 if full.
Definition: XrdPfc.hh:41