Skip to content

More efficient and movable Defer - #11005

Open
jschmidt-icinga wants to merge 1 commit into
masterfrom
defer-without-allocation
Open

More efficient and movable Defer#11005
jschmidt-icinga wants to merge 1 commit into
masterfrom
defer-without-allocation

Conversation

@jschmidt-icinga

@jschmidt-icinga jschmidt-icinga commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

This refactor makes Defer work without std::function by default and thus without all the overhead (like allocation and type erasure) that comes with it. It also makes Defer-objects movable. std::function<void()> is still supported by explicit instantiation along with void(*)() pointers when a fixed function type is needed with and without capture.

Other Changes

There are only two call-sites that needed to be adapted, ApiListener::ReplayLog() gets an explicitly instantiated Defer<std::function<void()>> so the code can keep using Defer::SetFunc(). And the use around ConfigPackageUtility gets an explicit Defer<void(*)()> because the type needs to be available in the header and thus can't be deduced.

Reasoning

Aside from the obvious efficiency gains the reason I started on this refactor was because I wanted to move a Defer object into a lambda-capture and noticed that it had the move constructor disabled. I then looked into what possible reason there could be for the disabled move constructor and didn't find any, but then noticed that by templating Defer and adding a deduction guide to a std::optional<lambda>, std::function could be avoided entirely. So this is a little more than the bare minimum I needed, but still it's a nice improvement, I think.

Additional Options

The changes in ConfigPackageUtility currently minimize the diff, but the Shared<Defer>::Ptr there could easily be avoided as well. This would however mean slight changes in the potential lifetime of the defer which should be evaluated carefully. I can do that in this PR if anyone wants me to.

@cla-bot cla-bot Bot added the cla/signed label Aug 24, 2026
@jschmidt-icinga
jschmidt-icinga force-pushed the defer-without-allocation branch 9 times, most recently from 7226921 to d5951f1 Compare August 26, 2026 09:22
The refactor makes `Defer` without `std::function` and thus without
all the overhead (like allocation and type erasure) that comes with
it.

I've also enabled the move constructor and assignment operators, whose
lack is what got me started on this refactor in the first place.

There are only two call-sites that needed to be adapted, one in ApiListener,
because the `SetFunc()` method has been removed. And one in/around
`ConfigPackageUtility` because that needs the type declared in the header
which gets (slightly) more complicated now.
@jschmidt-icinga
jschmidt-icinga force-pushed the defer-without-allocation branch from d5951f1 to fc6a2fa Compare August 26, 2026 09:26
@jschmidt-icinga
jschmidt-icinga marked this pull request as ready for review August 26, 2026 10:29
@jschmidt-icinga jschmidt-icinga added this to the 2.17.0 milestone Aug 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant