forked from mozilla/gecko-dev
-
Notifications
You must be signed in to change notification settings - Fork 1
/
InfallibleVector.h
151 lines (129 loc) · 4.48 KB
/
InfallibleVector.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_recordreplay_InfallibleVector_h
#define mozilla_recordreplay_InfallibleVector_h
#include "mozilla/Vector.h"
namespace mozilla {
namespace recordreplay {
// This file declares two classes, InfallibleVector and StaticInfallibleVector,
// which behave like normal vectors except that all their operations are
// infallible: we will immediately crash if any operation on the underlying
// vector fails.
//
// StaticInfallibleVector is designed for use in static storage, and does not
// have a static constructor or destructor in release builds.
template <typename Outer, typename T, size_t MinInlineCapacity,
class AllocPolicy>
class InfallibleVectorOperations {
typedef Vector<T, MinInlineCapacity, AllocPolicy> InnerVector;
InnerVector& Vector() { return static_cast<Outer*>(this)->Vector(); }
const InnerVector& Vector() const {
return static_cast<const Outer*>(this)->Vector();
}
public:
size_t length() const { return Vector().length(); }
bool empty() const { return Vector().empty(); }
T* begin() { return Vector().begin(); }
const T* begin() const { return Vector().begin(); }
T* end() { return Vector().end(); }
const T* end() const { return Vector().end(); }
T& operator[](size_t aIndex) { return Vector()[aIndex]; }
const T& operator[](size_t aIndex) const { return Vector()[aIndex]; }
T& back() { return Vector().back(); }
const T& back() const { return Vector().back(); }
void popBack() { Vector().popBack(); }
T popCopy() { return Vector().popCopy(); }
void erase(T* aT) { Vector().erase(aT); }
void clear() { Vector().clear(); }
void reserve(size_t aRequest) {
if (!Vector().reserve(aRequest)) {
MOZ_CRASH();
}
}
void resize(size_t aNewLength) {
if (!Vector().resize(aNewLength)) {
MOZ_CRASH();
}
}
template <typename U>
void append(U&& aU) {
if (!Vector().append(std::forward<U>(aU))) {
MOZ_CRASH();
}
}
template <typename U>
void append(const U* aBegin, size_t aLength) {
if (!Vector().append(aBegin, aLength)) {
MOZ_CRASH();
}
}
void appendN(const T& aT, size_t aN) {
if (!Vector().appendN(aT, aN)) {
MOZ_CRASH();
}
}
template <typename... Args>
void emplaceBack(Args&&... aArgs) {
if (!Vector().emplaceBack(std::forward<Args>(aArgs)...)) {
MOZ_CRASH();
}
}
template <typename... Args>
void infallibleEmplaceBack(Args&&... aArgs) {
Vector().infallibleEmplaceBack(std::forward<Args>(aArgs)...);
}
template <typename U>
void insert(T* aP, U&& aVal) {
if (!Vector().insert(aP, std::forward<U>(aVal))) {
MOZ_CRASH();
}
}
};
template <typename T, size_t MinInlineCapacity = 0,
class AllocPolicy = MallocAllocPolicy>
class InfallibleVector
: public InfallibleVectorOperations<
InfallibleVector<T, MinInlineCapacity, AllocPolicy>, T,
MinInlineCapacity, AllocPolicy> {
typedef Vector<T, MinInlineCapacity, AllocPolicy> InnerVector;
InnerVector mVector;
public:
InnerVector& Vector() { return mVector; }
const InnerVector& Vector() const { return mVector; }
};
template <typename T, size_t MinInlineCapacity = 0,
class AllocPolicy = MallocAllocPolicy>
class StaticInfallibleVector
: public InfallibleVectorOperations<
StaticInfallibleVector<T, MinInlineCapacity, AllocPolicy>, T,
MinInlineCapacity, AllocPolicy> {
typedef Vector<T, MinInlineCapacity, AllocPolicy> InnerVector;
mutable InnerVector* mVector;
void EnsureVector() const {
if (!mVector) {
// N.B. This class can only be used with alloc policies that have a
// default constructor.
AllocPolicy policy;
void* memory = policy.template pod_malloc<InnerVector>(1);
MOZ_RELEASE_ASSERT(memory);
mVector = new (memory) InnerVector();
}
}
public:
// InfallibleVectors are allocated in static storage and should not have
// constructors. Their memory will be initially zero.
InnerVector& Vector() {
EnsureVector();
return *mVector;
}
const InnerVector& Vector() const {
EnsureVector();
return *mVector;
}
};
} // namespace recordreplay
} // namespace mozilla
#endif // mozilla_recordreplay_InfallibleVector_h