GCC Code Coverage Report
Directory: cvmfs/ Exec Total Coverage
File: cvmfs/bigvector.h Lines: 88 92 95.7 %
Date: 2019-02-03 02:48:13 Branches: 33 86 38.4 %

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_