From e9cdb559e3d71efa57de467e43441134b164f2fe Mon Sep 17 00:00:00 2001 From: Matt Date: Fri, 8 Jan 2021 11:11:28 +0200 Subject: [PATCH] Avoid some allocations by using a fixed size vector --- src/openrct2/core/FixedVector.h | 176 +++++++++++++++++++++++++++++++ src/openrct2/libopenrct2.vcxproj | 3 +- src/openrct2/ride/Ride.cpp | 5 +- 3 files changed, 181 insertions(+), 3 deletions(-) create mode 100644 src/openrct2/core/FixedVector.h diff --git a/src/openrct2/core/FixedVector.h b/src/openrct2/core/FixedVector.h new file mode 100644 index 0000000000..f4e5908c44 --- /dev/null +++ b/src/openrct2/core/FixedVector.h @@ -0,0 +1,176 @@ +/***************************************************************************** + * Copyright (c) 2014-2021 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#pragma once + +#include "Guard.hpp" + +#include +#include +#include + +template class FixedVector +{ +public: + using container = std::array; + using iterator = typename container::iterator; + using const_iterator = typename container::const_iterator; + using reverse_iterator = typename container::reverse_iterator; + using const_reverse_iterator = typename container::const_reverse_iterator; + using value_type = typename container::value_type; + using reference_type = value_type&; + using const_reference_type = const value_type&; + + iterator begin() + { + if (_count == 0) + return _data.end(); + + return _data.begin(); + } + + iterator end() + { + if (_count == 0) + return _data.end(); + return begin() + _count; + } + + const_iterator cbegin() const + { + if (_count == 0) + return _data.cend(); + + return _data.cbegin(); + } + + const_iterator cend() const + { + if (_count == 0) + return _data.cend(); + return cbegin() + _count; + } + + reverse_iterator rbegin() + { + if (_count == 0) + return _data.rend(); + return _data.rbegin() + (MAX - _count); + } + + reverse_iterator rend() + { + return _data.rend(); + } + + const_reverse_iterator rbegin() const + { + return _data.rbegin() + (MAX - _count); + } + + const_reverse_iterator rend() const + { + return _data.rend(); + } + + reference_type back() + { + return _data[_count - 1]; + } + + const_reference_type back() const + { + return _data[_count - 1]; + } + + void push_back(const T& val) + { + Guard::Assert(_count < MAX); + _data[_count++] = val; + } + + void push_back(T&& val) + { + Guard::Assert(_count < MAX); + _data[_count++] = std::move(val); + } + + iterator insert(iterator pos, const T& val) + { + // Make sure the end iterator is correct. + auto itCurEnd = end(); + push_back(val); + + // Shift all elements to the right + auto offset = pos - begin(); + std::rotate(_data.begin(), pos, itCurEnd); + + return _data.begin() + offset; + } + + iterator insert(iterator pos, T&& val) + { + // Make sure the end iterator is correct. + auto itCurEnd = end(); + emplace_back(std::move(val)); + + // Shift all elements to the right + auto offset = pos - begin(); + std::rotate(_data.begin() + offset, itCurEnd, end()); + + return _data.begin() + offset; + } + + template reference_type emplace_back(Args&&... args) + { + Guard::Assert(_count < MAX); + reference_type res = _data[_count++]; + ::new (&res) T(std::forward(args)...); + return res; + } + + reference_type operator[](const size_t n) + { + return _data[n]; + } + + const_reference_type operator[](const size_t n) const + { + return _data[n]; + } + + void pop_back() + { + _count--; + } + + void clear() + { + _count = 0; + } + + size_t size() const + { + return _count; + } + + size_t capacity() const + { + return _data.size(); + } + + bool empty() const + { + return _count == 0; + } + +private: + size_t _count = 0; + container _data; +}; diff --git a/src/openrct2/libopenrct2.vcxproj b/src/openrct2/libopenrct2.vcxproj index 267d41f755..f81520925b 100644 --- a/src/openrct2/libopenrct2.vcxproj +++ b/src/openrct2/libopenrct2.vcxproj @@ -177,6 +177,7 @@ + @@ -868,4 +869,4 @@ - + \ No newline at end of file diff --git a/src/openrct2/ride/Ride.cpp b/src/openrct2/ride/Ride.cpp index 43cf590c25..60b221daf1 100644 --- a/src/openrct2/ride/Ride.cpp +++ b/src/openrct2/ride/Ride.cpp @@ -24,6 +24,7 @@ #include "../audio/audio.h" #include "../common.h" #include "../config/Config.h" +#include "../core/FixedVector.h" #include "../core/Guard.hpp" #include "../interface/Window.h" #include "../localisation/Date.h" @@ -6938,7 +6939,7 @@ void sub_6CB945(Ride* ride) } } - std::vector locations; + FixedVector locations; for (StationIndex stationId = 0; stationId < MAX_STATIONS; ++stationId) { auto entrance = ride_get_entrance_location(ride, stationId); @@ -6959,7 +6960,7 @@ void sub_6CB945(Ride* ride) auto locationListIter = locations.cbegin(); for (const TileCoordsXYZD& locationCoords : locations) { - auto locationList = ++locationListIter; + auto locationList = std::next(locationListIter); bool duplicateLocation = false; while (locationList != locations.cend())