summaryrefslogtreecommitdiff
path: root/src/common/range_sets.inc
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2024-02-04 19:16:07 +0100
committerGravatar Fernando Sahmkow2024-02-05 11:06:52 +0100
commit0d5a3abeaefd3a1682c48a59c5a9170cfb0a39d0 (patch)
tree850cfea521da30809e93d4ab2ce69f649961a9a1 /src/common/range_sets.inc
parentNVDRV: Refactor HeapMapper to use RangeSets (diff)
downloadyuzu-0d5a3abeaefd3a1682c48a59c5a9170cfb0a39d0.tar.gz
yuzu-0d5a3abeaefd3a1682c48a59c5a9170cfb0a39d0.tar.xz
yuzu-0d5a3abeaefd3a1682c48a59c5a9170cfb0a39d0.zip
Buffer Cache: Refactor to use Range sets instead
Diffstat (limited to '')
-rw-r--r--src/common/range_sets.inc184
1 files changed, 103 insertions, 81 deletions
diff --git a/src/common/range_sets.inc b/src/common/range_sets.inc
index fa55a68fb..705ebd4a1 100644
--- a/src/common/range_sets.inc
+++ b/src/common/range_sets.inc
@@ -6,9 +6,6 @@
6#include <limits> 6#include <limits>
7#include <utility> 7#include <utility>
8 8
9#define BOOST_NO_MT
10#include <boost/pool/detail/mutex.hpp>
11#undef BOOST_NO_MT
12#include <boost/icl/interval.hpp> 9#include <boost/icl/interval.hpp>
13#include <boost/icl/interval_base_set.hpp> 10#include <boost/icl/interval_base_set.hpp>
14#include <boost/icl/interval_map.hpp> 11#include <boost/icl/interval_map.hpp>
@@ -20,18 +17,16 @@
20 17
21#include "common/range_sets.h" 18#include "common/range_sets.h"
22 19
23namespace boost {
24template <typename T>
25class fast_pool_allocator<T, default_user_allocator_new_delete, details::pool::null_mutex, 4096, 0>;
26}
27
28namespace Common { 20namespace Common {
29 21
30template <typename AddressType> 22template <typename AddressType>
31struct RangeSet<AddressType>::RangeSetImpl { 23struct RangeSet<AddressType>::RangeSetImpl {
24 template <class T>
25 using MyAllocator = boost::fast_pool_allocator<T, boost::default_user_allocator_new_delete,
26 boost::details::pool::default_mutex, 1024, 2048>;
32 using IntervalSet = boost::icl::interval_set< 27 using IntervalSet = boost::icl::interval_set<
33 AddressType, std::less, ICL_INTERVAL_INSTANCE(ICL_INTERVAL_DEFAULT, AddressType, std::less), 28 AddressType, std::less, ICL_INTERVAL_INSTANCE(ICL_INTERVAL_DEFAULT, AddressType, std::less),
34 boost::fast_pool_allocator>; 29 MyAllocator>;
35 using IntervalType = typename IntervalSet::interval_type; 30 using IntervalType = typename IntervalSet::interval_type;
36 31
37 RangeSetImpl() = default; 32 RangeSetImpl() = default;
@@ -49,18 +44,58 @@ struct RangeSet<AddressType>::RangeSetImpl {
49 m_ranges_set.subtract(interval); 44 m_ranges_set.subtract(interval);
50 } 45 }
51 46
47 template <typename Func>
48 void ForEach(Func&& func) const {
49 if (m_ranges_set.empty()) {
50 return;
51 }
52 auto it = m_ranges_set.begin();
53 auto end_it = m_ranges_set.end();
54 for (; it != end_it; it++) {
55 const AddressType inter_addr_end = it->upper();
56 const AddressType inter_addr = it->lower();
57 func(inter_addr, inter_addr_end);
58 }
59 }
60
61 template <typename Func>
62 void ForEachInRange(AddressType base_addr, size_t size, Func&& func) const {
63 if (m_ranges_set.empty()) {
64 return;
65 }
66 const AddressType start_address = base_addr;
67 const AddressType end_address = start_address + size;
68 const RangeSetImpl::IntervalType search_interval{start_address, end_address};
69 auto it = m_ranges_set.lower_bound(search_interval);
70 if (it == m_ranges_set.end()) {
71 return;
72 }
73 auto end_it = m_ranges_set.upper_bound(search_interval);
74 for (; it != end_it; it++) {
75 AddressType inter_addr_end = it->upper();
76 AddressType inter_addr = it->lower();
77 if (inter_addr_end > end_address) {
78 inter_addr_end = end_address;
79 }
80 if (inter_addr < start_address) {
81 inter_addr = start_address;
82 }
83 func(inter_addr, inter_addr_end);
84 }
85 }
86
52 IntervalSet m_ranges_set; 87 IntervalSet m_ranges_set;
53}; 88};
54 89
55template <typename AddressType> 90template <typename AddressType>
56struct SplitRangeSet<AddressType>::SplitRangeSetImpl { 91struct SplitRangeSet<AddressType>::SplitRangeSetImpl {
57 92 template <class T>
58 using IntervalSet = 93 using MyAllocator = boost::fast_pool_allocator<T, boost::default_user_allocator_new_delete,
59 boost::icl::split_interval_map<AddressType, s32, boost::icl::partial_enricher, std::less, 94 boost::details::pool::default_mutex, 1024, 2048>;
60 boost::icl::inplace_plus, boost::icl::inter_section, 95 using IntervalSet = boost::icl::split_interval_map<
61 ICL_INTERVAL_INSTANCE(ICL_INTERVAL_DEFAULT, AddressType, 96 AddressType, s32, boost::icl::partial_enricher, std::less, boost::icl::inplace_plus,
62 std::less), 97 boost::icl::inter_section,
63 boost::fast_pool_allocator>; 98 ICL_INTERVAL_INSTANCE(ICL_INTERVAL_DEFAULT, AddressType, std::less), MyAllocator>;
64 using IntervalType = typename IntervalSet::interval_type; 99 using IntervalType = typename IntervalSet::interval_type;
65 100
66 SplitRangeSetImpl() = default; 101 SplitRangeSetImpl() = default;
@@ -75,6 +110,9 @@ struct SplitRangeSet<AddressType>::SplitRangeSetImpl {
75 template <bool has_on_delete, typename Func> 110 template <bool has_on_delete, typename Func>
76 void Subtract(AddressType base_address, size_t size, s32 amount, 111 void Subtract(AddressType base_address, size_t size, s32 amount,
77 [[maybe_unused]] Func&& on_delete) { 112 [[maybe_unused]] Func&& on_delete) {
113 if (m_split_ranges_set.empty()) {
114 return;
115 }
78 AddressType end_address = base_address + static_cast<AddressType>(size); 116 AddressType end_address = base_address + static_cast<AddressType>(size);
79 IntervalType interval{base_address, end_address}; 117 IntervalType interval{base_address, end_address};
80 bool any_removals = false; 118 bool any_removals = false;
@@ -101,6 +139,47 @@ struct SplitRangeSet<AddressType>::SplitRangeSetImpl {
101 } while (any_removals); 139 } while (any_removals);
102 } 140 }
103 141
142 template <typename Func>
143 void ForEach(Func&& func) const {
144 if (m_split_ranges_set.empty()) {
145 return;
146 }
147 auto it = m_split_ranges_set.begin();
148 auto end_it = m_split_ranges_set.end();
149 for (; it != end_it; it++) {
150 const AddressType inter_addr_end = it->first.upper();
151 const AddressType inter_addr = it->first.lower();
152 func(inter_addr, inter_addr_end, it->second);
153 }
154 }
155
156 template <typename Func>
157 void ForEachInRange(AddressType base_address, size_t size, Func&& func) const {
158 if (m_split_ranges_set.empty()) {
159 return;
160 }
161 const AddressType start_address = base_address;
162 const AddressType end_address = start_address + size;
163 const SplitRangeSetImpl::IntervalType search_interval{start_address, end_address};
164 auto it = m_split_ranges_set.lower_bound(search_interval);
165 if (it == m_split_ranges_set.end()) {
166 return;
167 }
168 auto end_it = m_split_ranges_set.upper_bound(search_interval);
169 for (; it != end_it; it++) {
170 auto& inter = it->first;
171 AddressType inter_addr_end = inter.upper();
172 AddressType inter_addr = inter.lower();
173 if (inter_addr_end > end_address) {
174 inter_addr_end = end_address;
175 }
176 if (inter_addr < start_address) {
177 inter_addr = start_address;
178 }
179 func(inter_addr, inter_addr_end, it->second);
180 }
181 }
182
104 IntervalSet m_split_ranges_set; 183 IntervalSet m_split_ranges_set;
105}; 184};
106 185
@@ -146,41 +225,13 @@ bool RangeSet<AddressType>::Empty() const {
146template <typename AddressType> 225template <typename AddressType>
147template <typename Func> 226template <typename Func>
148void RangeSet<AddressType>::ForEach(Func&& func) const { 227void RangeSet<AddressType>::ForEach(Func&& func) const {
149 if (m_impl->m_ranges_set.empty()) { 228 m_impl->ForEach(std::move(func));
150 return;
151 }
152 auto it = m_impl->m_ranges_set.begin();
153 auto end_it = m_impl->m_ranges_set.end();
154 for (; it != end_it; it++) {
155 const AddressType inter_addr_end = it->upper();
156 const AddressType inter_addr = it->lower();
157 func(inter_addr, inter_addr_end);
158 }
159} 229}
160 230
161template <typename AddressType> 231template <typename AddressType>
162template <typename Func> 232template <typename Func>
163void RangeSet<AddressType>::ForEachInRange(AddressType base_addr, size_t size, Func&& func) const { 233void RangeSet<AddressType>::ForEachInRange(AddressType base_address, size_t size, Func&& func) const {
164 auto& range_set = m_impl->m_ranges_set; 234 m_impl->ForEachInRange(base_address, size, std::move(func));
165 const AddressType start_address = base_addr;
166 const AddressType end_address = start_address + size;
167 const RangeSetImpl::IntervalType search_interval{start_address, end_address};
168 auto it = range_set.lower_bound(search_interval);
169 if (it == range_set.end()) {
170 return;
171 }
172 auto end_it = range_set.upper_bound(search_interval);
173 for (; it != end_it; it++) {
174 AddressType inter_addr_end = it->upper();
175 AddressType inter_addr = it->lower();
176 if (inter_addr_end > end_address) {
177 inter_addr_end = end_address;
178 }
179 if (inter_addr < start_address) {
180 inter_addr = start_address;
181 }
182 func(inter_addr, inter_addr_end);
183 }
184} 235}
185 236
186template <typename AddressType> 237template <typename AddressType>
@@ -209,18 +260,18 @@ void SplitRangeSet<AddressType>::Add(AddressType base_address, size_t size) {
209 260
210template <typename AddressType> 261template <typename AddressType>
211void SplitRangeSet<AddressType>::Subtract(AddressType base_address, size_t size) { 262void SplitRangeSet<AddressType>::Subtract(AddressType base_address, size_t size) {
212 m_impl->Subtract<false>(base_address, size, 1, [](AddressType, AddressType) {}); 263 m_impl->template Subtract<false>(base_address, size, 1, [](AddressType, AddressType) {});
213} 264}
214 265
215template <typename AddressType> 266template <typename AddressType>
216template <typename Func> 267template <typename Func>
217void SplitRangeSet<AddressType>::Subtract(AddressType base_address, size_t size, Func&& on_delete) { 268void SplitRangeSet<AddressType>::Subtract(AddressType base_address, size_t size, Func&& on_delete) {
218 m_impl->Subtract<true>(base_address, size, 1, on_delete); 269 m_impl->template Subtract<true, Func>(base_address, size, 1, std::move(on_delete));
219} 270}
220 271
221template <typename AddressType> 272template <typename AddressType>
222void SplitRangeSet<AddressType>::DeleteAll(AddressType base_address, size_t size) { 273void SplitRangeSet<AddressType>::DeleteAll(AddressType base_address, size_t size) {
223 m_impl->Subtract<false>(base_address, size, std::numeric_limits<s32>::max(), 274 m_impl->template Subtract<false>(base_address, size, std::numeric_limits<s32>::max(),
224 [](AddressType, AddressType) {}); 275 [](AddressType, AddressType) {});
225} 276}
226 277
@@ -237,43 +288,14 @@ bool SplitRangeSet<AddressType>::Empty() const {
237template <typename AddressType> 288template <typename AddressType>
238template <typename Func> 289template <typename Func>
239void SplitRangeSet<AddressType>::ForEach(Func&& func) const { 290void SplitRangeSet<AddressType>::ForEach(Func&& func) const {
240 if (m_impl->m_split_ranges_set.empty()) { 291 m_impl->ForEach(func);
241 return;
242 }
243 auto it = m_impl->m_split_ranges_set.begin();
244 auto end_it = m_impl->m_split_ranges_set.end();
245 for (; it != end_it; it++) {
246 const AddressType inter_addr_end = it->first.upper();
247 const AddressType inter_addr = it->first.lower();
248 func(inter_addr, inter_addr_end, it->second);
249 }
250} 292}
251 293
252template <typename AddressType> 294template <typename AddressType>
253template <typename Func> 295template <typename Func>
254void SplitRangeSet<AddressType>::ForEachInRange(AddressType base_address, size_t size, 296void SplitRangeSet<AddressType>::ForEachInRange(AddressType base_address, size_t size,
255 Func&& func) const { 297 Func&& func) const {
256 auto& range_set = m_impl->m_split_ranges_set; 298 m_impl->ForEachInRange(base_address, size, std::move(func));
257 const AddressType start_address = base_address;
258 const AddressType end_address = start_address + size;
259 const SplitRangeSetImpl::IntervalType search_interval{start_address, end_address};
260 auto it = range_set.lower_bound(search_interval);
261 if (it == range_set.end()) {
262 return;
263 }
264 auto end_it = range_set.upper_bound(search_interval);
265 for (; it != end_it; it++) {
266 auto& inter = it->first;
267 AddressType inter_addr_end = inter.upper();
268 AddressType inter_addr = inter.lower();
269 if (inter_addr_end > end_address) {
270 inter_addr_end = end_address;
271 }
272 if (inter_addr < start_address) {
273 inter_addr = start_address;
274 }
275 func(inter_addr, inter_addr_end, it->second);
276 }
277} 299}
278 300
279} // namespace Common \ No newline at end of file 301} // namespace Common \ No newline at end of file