GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/bigvector.h
Date: 2026-10-25 02:40:14
Exec Total Coverage
Lines: 105 106 99.1%
Branches: 31 44 70.5%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 *
4 * Dynamic array, allocate with mmap for large arrays.
5 */
6
7 #ifndef CVMFS_BIGVECTOR_H_
8 #define CVMFS_BIGVECTOR_H_
9
10 #include <cassert>
11 #include <cstdlib>
12
13 #include "util/smalloc.h"
14
15 template<class Item>
16 class BigVector {
17 public:
18 8871 BigVector() {
19 8871 buffer_ = Alloc(kNumInit);
20 8871 size_ = 0;
21 8871 shared_buffer_ = false;
22 8871 }
23
24 8370023 explicit BigVector(const size_t num_items) {
25
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8370023 times.
8370023 assert(num_items > 0);
26 8370023 buffer_ = Alloc(num_items);
27 8370023 size_ = 0;
28 8370023 shared_buffer_ = false;
29 8370023 }
30
31 16505431 BigVector(const BigVector<Item> &other) { CopyFrom(other); }
32
33 99 BigVector<Item> &operator=(const BigVector<Item> &other) {
34
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 99 times.
99 if (&other == this)
35 ✗ return *this;
36
37
1/2
✓ Branch 0 taken 99 times.
✗ Branch 1 not taken.
99 if (!shared_buffer_)
38 99 Dealloc();
39 99 CopyFrom(other);
40 99 return *this;
41 }
42
43 49725106 ~BigVector() {
44
1/2
✓ Branch 0 taken 24863993 times.
✗ Branch 1 not taken.
49725106 if (!shared_buffer_)
45 49727743 Dealloc();
46 49742438 }
47
48 990524356 Item At(const size_t index) const {
49
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 990407472 times.
990524356 assert(index < size_);
50 990524356 return buffer_[index];
51 }
52
53 660057216 const Item *AtPtr(const size_t index) const {
54
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 660028608 times.
660057216 assert(index < size_);
55 660057216 return &buffer_[index];
56 }
57
58 1320287765 void PushBack(const Item &item) {
59
2/2
✓ Branch 0 taken 7527 times.
✓ Branch 1 taken 1320240807 times.
1320287765 if (size_ == capacity_)
60 7761 DoubleCapacity();
61
1/2
✓ Branch 2 taken 234 times.
✗ Branch 3 not taken.
1320287765 new (buffer_ + size_) Item(item);
62 1320287765 size_++;
63 1320287765 }
64
65 72157 void Replace(size_t index, const Item &item) {
66
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72157 times.
72157 assert(index < size_);
67 72157 buffer_[index] = item;
68 72157 }
69
70 171 bool IsEmpty() const { return size_ == 0; }
71
72 93 void Clear() {
73 93 Dealloc();
74 93 buffer_ = Alloc(kNumInit);
75 93 }
76
77 33 void ShareBuffer(Item **duplicate, bool *large_alloc) {
78 33 *duplicate = buffer_;
79 33 *large_alloc = large_alloc_;
80 33 shared_buffer_ = true;
81 33 }
82
83 7761 void DoubleCapacity() {
84 7761 Item *old_buffer = buffer_;
85 7761 const bool old_large_alloc = large_alloc_;
86
87
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7527 times.
7761 assert(capacity_ > 0);
88 7761 buffer_ = Alloc(capacity_ * 2);
89
2/2
✓ Branch 0 taken 2214827097 times.
✓ Branch 1 taken 7527 times.
2214874170 for (size_t i = 0; i < size_; ++i)
90
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2214866409 new (buffer_ + i) Item(old_buffer[i]);
91
92 7761 FreeBuffer(old_buffer, size_, old_large_alloc);
93 7761 }
94
95 39223 void ShrinkIfOversized() {
96
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39223 times.
39223 assert(!shared_buffer_);
97
98
2/2
✓ Branch 0 taken 820 times.
✓ Branch 1 taken 38403 times.
39223 if (size_ <= kNumInit)
99 820 return;
100
2/2
✓ Branch 0 taken 38214 times.
✓ Branch 1 taken 189 times.
38403 if (static_cast<float>(size_) >= (0.25 * static_cast<float>(capacity_)))
101 38214 return;
102
103 189 bool const old_large_alloc = large_alloc_;
104 189 Item *new_buffer = Alloc(0.5 * static_cast<float>(capacity_));
105
2/2
✓ Branch 0 taken 21864 times.
✓ Branch 1 taken 189 times.
22053 for (size_t i = 0; i < size_; ++i)
106 21864 new (new_buffer + i) Item(buffer_[i]);
107 189 FreeBuffer(buffer_, size_, old_large_alloc);
108 189 buffer_ = new_buffer;
109 }
110
111 // Careful! Only for externally modified buffer.
112 39223 void SetSize(const size_t new_size) {
113
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39223 times.
39223 assert(new_size <= capacity_);
114 39223 size_ = new_size;
115 39223 }
116
117 33332797 size_t size() const { return size_; }
118 528 size_t capacity() const { return capacity_; }
119
120 private:
121 static const size_t kNumInit = 16;
122 static const size_t kMmapThreshold = 128 * 1024;
123
124 24888226 Item *Alloc(const size_t num_elements) {
125 Item *result;
126 24888226 const size_t num_bytes = sizeof(Item) * num_elements;
127
2/2
✓ Branch 0 taken 1458 times.
✓ Branch 1 taken 24885360 times.
24888226 if (num_bytes >= kMmapThreshold) {
128 1497 result = static_cast<Item *>(smmap(num_bytes));
129 1497 large_alloc_ = true;
130 } else {
131 24886729 result = static_cast<Item *>(smalloc(num_bytes));
132 24883990 large_alloc_ = false;
133 }
134 24885487 capacity_ = num_elements;
135 24885487 return result;
136 }
137
138 49723627 void Dealloc() {
139 49723627 FreeBuffer(buffer_, size_, large_alloc_);
140 49747187 buffer_ = NULL;
141 49747187 capacity_ = 0;
142 49747187 size_ = 0;
143 49747187 }
144
145 24874315 void FreeBuffer(Item *buf, const size_t size, const bool large) {
146
2/2
✓ Branch 0 taken 3535088443 times.
✓ Branch 1 taken 24869837 times.
3560205227 for (size_t i = 0; i < size; ++i)
147 3535330912 buf[i].~Item();
148
149
2/2
✓ Branch 0 taken 24869802 times.
✓ Branch 1 taken 35 times.
24874315 if (buf) {
150
2/2
✓ Branch 0 taken 1425 times.
✓ Branch 1 taken 24868377 times.
24874280 if (large) {
151 1464 smunmap(buf);
152 } else {
153 24872816 free(buf);
154 }
155 }
156 24874315 }
157
158 16505398 void CopyFrom(const BigVector<Item> &other) {
159 16505398 buffer_ = Alloc(other.capacity_);
160
2/2
✓ Branch 0 taken 660027159 times.
✓ Branch 1 taken 16505563 times.
676532722 for (size_t i = 0; i < other.size_; ++i) {
161 660027159 new (buffer_ + i) Item(*other.AtPtr(i));
162 }
163 16505563 size_ = other.size_;
164 16505563 shared_buffer_ = false;
165 16505563 }
166
167 Item *buffer_;
168 size_t size_;
169 size_t capacity_;
170 bool large_alloc_;
171 bool shared_buffer_;
172 };
173
174 #endif // CVMFS_BIGVECTOR_H_
175