mirror of
https://github.com/gperftools/gperftools
synced 2025-01-03 05:02:04 +00:00
modernize and fix SpanSet iterator handling
In addition to just being more readable, we fix github issue #1573 "Unable to build gperftools with _GLIBCXX_DEBUG flag".
This commit is contained in:
parent
e9fbbf9450
commit
c4120da88e
@ -279,7 +279,7 @@ Span* PageHeap::AllocLarge(Length n) {
|
||||
bound.length = n;
|
||||
|
||||
// First search the NORMAL spans..
|
||||
SpanSet::iterator place = large_normal_.upper_bound(SpanPtrWithLength(&bound));
|
||||
SpanSetIter place = large_normal_.upper_bound(SpanPtrWithLength(&bound));
|
||||
if (place != large_normal_.end()) {
|
||||
best = place->span;
|
||||
best_normal = best;
|
||||
@ -512,7 +512,7 @@ void PageHeap::PrependToFreeList(Span* span) {
|
||||
SpanSet *set = &large_normal_;
|
||||
if (span->location == Span::ON_RETURNED_FREELIST)
|
||||
set = &large_returned_;
|
||||
std::pair<SpanSet::iterator, bool> p =
|
||||
std::pair<SpanSetIter, bool> p =
|
||||
set->insert(SpanPtrWithLength(span));
|
||||
ASSERT(p.second); // We never have duplicates since span->start is unique.
|
||||
span->SetSpanSetIterator(p.first);
|
||||
@ -539,7 +539,7 @@ void PageHeap::RemoveFromFreeList(Span* span) {
|
||||
SpanSet *set = &large_normal_;
|
||||
if (span->location == Span::ON_RETURNED_FREELIST)
|
||||
set = &large_returned_;
|
||||
SpanSet::iterator iter = span->ExtractSpanSetIterator();
|
||||
SpanSetIter iter = span->ExtractSpanSetIterator();
|
||||
ASSERT(iter->span == span);
|
||||
ASSERT(set->find(SpanPtrWithLength(span)) == iter);
|
||||
set->erase(iter);
|
||||
@ -682,11 +682,11 @@ void PageHeap::GetLargeSpanStatsLocked(LargeSpanStats* result) {
|
||||
result->spans = 0;
|
||||
result->normal_pages = 0;
|
||||
result->returned_pages = 0;
|
||||
for (SpanSet::iterator it = large_normal_.begin(); it != large_normal_.end(); ++it) {
|
||||
for (SpanSetIter it = large_normal_.begin(); it != large_normal_.end(); ++it) {
|
||||
result->normal_pages += it->length;
|
||||
result->spans++;
|
||||
}
|
||||
for (SpanSet::iterator it = large_returned_.begin(); it != large_returned_.end(); ++it) {
|
||||
for (SpanSetIter it = large_returned_.begin(); it != large_returned_.end(); ++it) {
|
||||
result->returned_pages += it->length;
|
||||
result->spans++;
|
||||
}
|
||||
@ -817,7 +817,7 @@ bool PageHeap::CheckList(Span* list, Length min_pages, Length max_pages,
|
||||
}
|
||||
|
||||
bool PageHeap::CheckSet(SpanSet* spanset, Length min_pages,int freelist) {
|
||||
for (SpanSet::iterator it = spanset->begin(); it != spanset->end(); ++it) {
|
||||
for (SpanSetIter it = spanset->begin(); it != spanset->end(); ++it) {
|
||||
Span* s = it->span;
|
||||
CHECK_CONDITION(s->length == it->length);
|
||||
CHECK_CONDITION(s->location == freelist); // NORMAL or RETURNED
|
||||
|
28
src/span.h
28
src/span.h
@ -44,7 +44,6 @@
|
||||
|
||||
namespace tcmalloc {
|
||||
|
||||
struct SpanBestFitLess;
|
||||
struct Span;
|
||||
|
||||
// Store a pointer to a span along with a cached copy of its length.
|
||||
@ -58,13 +57,14 @@ struct SpanPtrWithLength {
|
||||
Span* span;
|
||||
Length length;
|
||||
};
|
||||
typedef std::set<SpanPtrWithLength, SpanBestFitLess, STLPageHeapAllocator<SpanPtrWithLength, void> > SpanSet;
|
||||
|
||||
// Comparator for best-fit search, with address order as a tie-breaker.
|
||||
struct SpanBestFitLess {
|
||||
bool operator()(SpanPtrWithLength a, SpanPtrWithLength b) const;
|
||||
};
|
||||
|
||||
using SpanSet = std::set<SpanPtrWithLength, SpanBestFitLess, STLPageHeapAllocator<SpanPtrWithLength, void>>;
|
||||
using SpanSetIter = SpanSet::iterator;
|
||||
|
||||
// Information kept for a span (a contiguous run of pages).
|
||||
struct Span {
|
||||
PageID start; // Starting page number
|
||||
@ -78,7 +78,7 @@ struct Span {
|
||||
// this span into set of large spans. It is used to quickly delete
|
||||
// spans from those sets. span_iter_space is space for such
|
||||
// iterator which lifetime is controlled explicitly.
|
||||
char span_iter_space[sizeof(SpanSet::iterator)];
|
||||
alignas(SpanSetIter) char span_iter_space[sizeof(SpanSetIter)];
|
||||
};
|
||||
unsigned int refcount : 16; // Number of non-free objects
|
||||
unsigned int sizeclass : 8; // Size-class for small objects (or 0)
|
||||
@ -92,9 +92,9 @@ struct Span {
|
||||
|
||||
// Sets iterator stored in span_iter_space.
|
||||
// Requires has_span_iter == 0.
|
||||
void SetSpanSetIterator(const SpanSet::iterator& iter);
|
||||
void SetSpanSetIterator(const SpanSetIter& iter);
|
||||
// Copies out and destroys iterator stored in span_iter_space.
|
||||
SpanSet::iterator ExtractSpanSetIterator();
|
||||
SpanSetIter ExtractSpanSetIterator();
|
||||
|
||||
// What freelist the span is on: IN_USE if on none, or normal or returned
|
||||
enum { IN_USE, ON_NORMAL_FREELIST, ON_RETURNED_FREELIST };
|
||||
@ -113,23 +113,21 @@ inline bool SpanBestFitLess::operator()(SpanPtrWithLength a, SpanPtrWithLength b
|
||||
return a.span->start < b.span->start;
|
||||
}
|
||||
|
||||
inline void Span::SetSpanSetIterator(const SpanSet::iterator& iter) {
|
||||
inline void Span::SetSpanSetIterator(const SpanSetIter& iter) {
|
||||
ASSERT(!has_span_iter);
|
||||
has_span_iter = 1;
|
||||
|
||||
new (span_iter_space) SpanSet::iterator(iter);
|
||||
new (span_iter_space) SpanSetIter(iter);
|
||||
}
|
||||
|
||||
inline SpanSet::iterator Span::ExtractSpanSetIterator() {
|
||||
typedef SpanSet::iterator iterator_type;
|
||||
|
||||
inline SpanSetIter Span::ExtractSpanSetIterator() {
|
||||
ASSERT(has_span_iter);
|
||||
has_span_iter = 0;
|
||||
|
||||
iterator_type* this_iter =
|
||||
reinterpret_cast<iterator_type*>(span_iter_space);
|
||||
iterator_type retval = *this_iter;
|
||||
this_iter->~iterator_type();
|
||||
SpanSetIter* this_iter =
|
||||
reinterpret_cast<SpanSetIter*>(span_iter_space);
|
||||
SpanSetIter retval = *this_iter;
|
||||
this_iter->~SpanSetIter();
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user