/* -*- 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 class InfallibleVectorOperations { typedef Vector InnerVector; InnerVector& Vector() { return static_cast(this)->Vector(); } const InnerVector& Vector() const { return static_cast(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 void append(U&& aU) { if (!Vector().append(std::forward(aU))) { MOZ_CRASH(); } } template 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 void emplaceBack(Args&&... aArgs) { if (!Vector().emplaceBack(std::forward(aArgs)...)) { MOZ_CRASH(); } } template void infallibleEmplaceBack(Args&&... aArgs) { Vector().infallibleEmplaceBack(std::forward(aArgs)...); } template void insert(T* aP, U&& aVal) { if (!Vector().insert(aP, std::forward(aVal))) { MOZ_CRASH(); } } }; template class InfallibleVector : public InfallibleVectorOperations, T, MinInlineCapacity, AllocPolicy> { typedef Vector InnerVector; InnerVector mVector; public: InnerVector& Vector() { return mVector; } const InnerVector& Vector() const { return mVector; } }; template class StaticInfallibleVector : public InfallibleVectorOperations, T, MinInlineCapacity, AllocPolicy> { typedef Vector 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(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