XRootD
Loading...
Searching...
No Matches
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
8namespace XrdPfc {
9
10//==============================================================================
11// StableChunkVector
12//==============================================================================
13
19
20template<typename T, unsigned InnerShift = 12, unsigned MaxChunks = 1024>
22{
23public:
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
56private:
57 std::vector<std::vector<T>> m_chunks;
58 std::size_t m_size = 0;
59};
60
61
62//==============================================================================
63// StableChunkPool
64//==============================================================================
65
69
70template<typename T, unsigned InnerShift = 12, unsigned MaxChunks = 1024>
71class StableChunkPool : public StableChunkVector<T, InnerShift, MaxChunks>
72{
74
75public:
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
99private:
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
int add()
Append a default-constructed T; return its index, or -1 if full.