logalloc: relax lifetime rules around region_listener

Currently, a region_listener is added during construction and removed
during destruction. This was done to mimick the old region(region_group&)
constructor, as region_listener replaces region_group.

However, this makes moving the binomial heap handle outside logalloc
difficult. The natural place for the handle is in a derived class
of logalloc::region (e.g. memtable), but members of this derived class
will be destroyed earlier than the logalloc::region here. We could play
trickes with an earlier base class but it's better to just decouple
region lifecycle from listener lifecycle.

Do that be adding listen()/unlisten() methods. Some small awkwardness
remains in that merge() implicitly unlistens (see comment in
region::unlisten).

Unit tests are adjusted.
This commit is contained in:
Avi Kivity
2022-06-22 18:57:03 +03:00
parent fbe8ea7727
commit ee720fa23b
4 changed files with 70 additions and 27 deletions

View File

@@ -1741,8 +1741,8 @@ private:
};
public:
explicit region_impl(region* region, region_listener* listener = nullptr)
: _region(region), _listener(listener), _id(next_id())
explicit region_impl(region* region)
: _region(region), _id(next_id())
{
_buf_ptrs_for_compact_segment.reserve(segment::size / buf_align);
_preferred_max_contiguous_allocation = max_managed_object_size;
@@ -1780,6 +1780,21 @@ public:
return occupancy().used_space() == 0;
}
void listen(region_listener* listener) {
_listener = listener;
_listener->add(_region);
}
void unlisten() {
// _listener may have been removed be merge(), so check for that.
// Yes, it's awkward, we should have the caller unlisten before merge
// to remove implicit behavior.
if (_listener) {
_listener->del(_region);
_listener = nullptr;
}
}
occupancy_stats occupancy() const {
occupancy_stats total = _non_lsa_occupancy;
total += _closed_occupancy;
@@ -2111,9 +2126,14 @@ region::region()
: _impl(make_shared<impl>(this))
{ }
region::region(region_listener& listener)
: _impl(make_shared<impl>(this, &listener)) {
listener.add(this);
void
region::listen(region_listener* listener) {
get_impl().listen(listener);
}
void
region::unlisten() {
get_impl().unlisten();
}
region_impl& region::get_impl() {

View File

@@ -301,12 +301,14 @@ private:
const region_impl& get_impl() const;
public:
region();
explicit region(region_listener& listener);
~region();
region(region&& other);
region& operator=(region&& other);
region(const region& other) = delete;
void listen(region_listener* listener);
void unlisten();
occupancy_stats occupancy() const;
allocation_strategy& allocator() noexcept {