GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
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 "smalloc.h" |
||
14 |
|||
15 |
template<class Item> |
||
16 |
class BigVector { |
||
17 |
public: |
||
18 |
129 |
BigVector() { |
|
19 |
129 |
Alloc(kNumInit); |
|
20 |
129 |
size_ = 0; |
|
21 |
129 |
shared_buffer_ = false; |
|
22 |
129 |
} |
|
23 |
|||
24 |
958 |
explicit BigVector(const size_t num_items) { |
|
25 |
✗✓ | 958 |
assert(num_items > 0); |
26 |
958 |
Alloc(num_items); |
|
27 |
958 |
size_ = 0; |
|
28 |
958 |
shared_buffer_ = false; |
|
29 |
958 |
} |
|
30 |
|||
31 |
319 |
BigVector(const BigVector<Item> &other) { |
|
32 |
319 |
CopyFrom(other); |
|
33 |
319 |
} |
|
34 |
|||
35 |
9 |
BigVector<Item> &operator= (const BigVector<Item> &other) { |
|
36 |
✗✓ | 9 |
if (&other == this) |
37 |
return *this; |
||
38 |
|||
39 |
✓✗ | 9 |
if (!shared_buffer_) |
40 |
9 |
Dealloc(); |
|
41 |
9 |
CopyFrom(other); |
|
42 |
9 |
return *this; |
|
43 |
} |
||
44 |
|||
45 |
1403 |
~BigVector() { |
|
46 |
✓✓✓✗ ✗✗✗✗ |
1403 |
if (!shared_buffer_) |
47 |
1402 |
Dealloc(); |
|
48 |
1403 |
} |
|
49 |
|||
50 |
30011793 |
Item At(const size_t index) const { |
|
51 |
✗✓✗✗ |
30011793 |
assert(index < size_); |
52 |
30011793 |
return buffer_[index]; |
|
53 |
} |
||
54 |
|||
55 |
20003333 |
const Item *AtPtr(const size_t index) const { |
|
56 |
✗✓✗✓ |
20003333 |
assert(index < size_); |
57 |
20003333 |
return &buffer_[index]; |
|
58 |
} |
||
59 |
|||
60 |
30009892 |
void PushBack(const Item &item) { |
|
61 |
✓✓✗✓ |
30009892 |
if (size_ == capacity_) |
62 |
373 |
DoubleCapacity(); |
|
63 |
✓✗✓✗ |
30009892 |
new (buffer_ + size_) Item(item); |
64 |
30009892 |
size_++; |
|
65 |
30009892 |
} |
|
66 |
|||
67 |
3 |
bool IsEmpty() const { |
|
68 |
3 |
return size_ == 0; |
|
69 |
} |
||
70 |
|||
71 |
5 |
void Clear() { |
|
72 |
5 |
Dealloc(); |
|
73 |
5 |
Alloc(kNumInit); |
|
74 |
5 |
} |
|
75 |
|||
76 |
1 |
void ShareBuffer(Item **duplicate, bool *large_alloc) { |
|
77 |
1 |
*duplicate = buffer_; |
|
78 |
1 |
*large_alloc = large_alloc_; |
|
79 |
1 |
shared_buffer_ = true; |
|
80 |
1 |
} |
|
81 |
|||
82 |
373 |
void DoubleCapacity() { |
|
83 |
373 |
Item *old_buffer = buffer_; |
|
84 |
373 |
bool old_large_alloc = large_alloc_; |
|
85 |
|||
86 |
✗✓✗✗ |
373 |
assert(capacity_ > 0); |
87 |
373 |
Alloc(capacity_ * 2); |
|
88 |
✓✓✗✗ |
50341576 |
for (size_t i = 0; i < size_; ++i) |
89 |
✓✗✗✗ |
50341203 |
new (buffer_ + i) Item(old_buffer[i]); |
90 |
|||
91 |
373 |
FreeBuffer(old_buffer, size_, old_large_alloc); |
|
92 |
373 |
} |
|
93 |
|||
94 |
// Careful! Only for externally modified buffer. |
||
95 |
void SetSize(const size_t new_size) { |
||
96 |
assert(new_size <= capacity_); |
||
97 |
size_ = new_size; |
||
98 |
} |
||
99 |
|||
100 |
1473 |
size_t size() const { return size_; } |
|
101 |
10 |
size_t capacity() const { return capacity_; } |
|
102 |
|||
103 |
private: |
||
104 |
static const size_t kNumInit = 16; |
||
105 |
static const size_t kMmapThreshold = 128*1024; |
||
106 |
|||
107 |
1793 |
void Alloc(const size_t num_elements) { |
|
108 |
1793 |
size_t num_bytes = sizeof(Item) * num_elements; |
|
109 |
✓✓✗✓ ✗✗✗✗ |
1793 |
if (num_bytes >= kMmapThreshold) { |
110 |
32 |
buffer_ = static_cast<Item *>(smmap(num_bytes)); |
|
111 |
32 |
large_alloc_ = true; |
|
112 |
} else { |
||
113 |
1761 |
buffer_ = static_cast<Item *>(smalloc(num_bytes)); |
|
114 |
1761 |
large_alloc_ = false; |
|
115 |
} |
||
116 |
1793 |
capacity_ = num_elements; |
|
117 |
1793 |
} |
|
118 |
|||
119 |
1416 |
void Dealloc() { |
|
120 |
1416 |
FreeBuffer(buffer_, size_, large_alloc_); |
|
121 |
1416 |
buffer_ = NULL; |
|
122 |
1416 |
capacity_ = 0; |
|
123 |
1416 |
size_ = 0; |
|
124 |
1416 |
} |
|
125 |
|||
126 |
1789 |
void FreeBuffer(Item *buf, const size_t size, const bool large) { |
|
127 |
✓✓✓✓ ✗✗✗✗ ✗✗ |
80356176 |
for (size_t i = 0; i < size; ++i) |
128 |
80354387 |
buf[i].~Item(); |
|
129 |
|||
130 |
✓✗✓✗ ✗✗✗✗ ✗✗ |
1789 |
if (buf) { |
131 |
✓✓✗✓ ✗✗✗✗ ✗✗ |
1789 |
if (large) |
132 |
30 |
smunmap(buf); |
|
133 |
else |
||
134 |
1759 |
free(buf); |
|
135 |
} |
||
136 |
1789 |
} |
|
137 |
|||
138 |
328 |
void CopyFrom(const BigVector<Item> &other) { |
|
139 |
328 |
Alloc(other.capacity_); |
|
140 |
✓✓ | 20003620 |
for (size_t i = 0; i < other.size_; ++i) { |
141 |
✓✗ | 20003292 |
new (buffer_ + i) Item(*other.AtPtr(i)); |
142 |
} |
||
143 |
328 |
size_ = other.size_; |
|
144 |
328 |
shared_buffer_ = false; |
|
145 |
328 |
} |
|
146 |
|||
147 |
Item *buffer_; |
||
148 |
size_t size_; |
||
149 |
size_t capacity_; |
||
150 |
bool large_alloc_; |
||
151 |
bool shared_buffer_; |
||
152 |
}; |
||
153 |
|||
154 |
#endif // CVMFS_BIGVECTOR_H_ |
Generated by: GCOVR (Version 4.1) |