libutil: allow graceful dropping of Pool::Handle

not needed yet, but returning a resource from the exception handling
path that has ownership of a handle is currently not well-supported.
we could also add a default constructor to Handle, but then we would
also need to change the pool reference to a pointer. eventually that
should be done since now resources can be swapped between pools with
clever moves, but since that's not a problem yet we won't do it now.

Change-Id: I26eb06581f7be34569e9e67a33da736128d167af
This commit is contained in:
eldritch horrors 2024-03-21 23:50:10 +01:00
parent 567d7b3ab8
commit 8075541d82

View file

@ -108,6 +108,19 @@ public:
Handle(Pool & pool, std::shared_ptr<R> r) : pool(pool), r(r) { } Handle(Pool & pool, std::shared_ptr<R> r) : pool(pool), r(r) { }
void drop(bool stillValid)
{
{
auto state_(pool.state.lock());
if (stillValid)
state_->idle.emplace_back(std::move(r));
assert(state_->inUse);
state_->inUse--;
}
pool.wakeup.notify_one();
r = nullptr;
}
public: public:
Handle(Handle && h) : pool(h.pool), r(h.r) { h.r.reset(); } Handle(Handle && h) : pool(h.pool), r(h.r) { h.r.reset(); }
@ -115,15 +128,13 @@ public:
~Handle() ~Handle()
{ {
if (!r) return; if (r)
{ drop(std::uncaught_exceptions() == 0);
auto state_(pool.state.lock());
if (!std::uncaught_exceptions())
state_->idle.push_back(ref<R>(r));
assert(state_->inUse);
state_->inUse--;
} }
pool.wakeup.notify_one();
void release()
{
drop(true);
} }
R * operator -> () { return &*r; } R * operator -> () { return &*r; }