diff options
author | Anna Henningsen <anna@addaleax.net> | 2019-10-26 19:29:46 +0300 |
---|---|---|
committer | Myles Borins <mylesborins@google.com> | 2019-11-17 10:59:10 +0300 |
commit | 058a8d53631df7aba5fbbff8859ebc8e88fade49 (patch) | |
tree | 62e675c12684a8c4f09b68ea26fa8a45baab2330 /src/util.h | |
parent | 31a3b724f0ec4d246f6bf2538e2c401af8dc1552 (diff) |
src: do not use `std::function` for `OnScopeLeave`
Using `std::function` adds an extra layer of indirection, and in
particular, heap allocations that are not necessary in our use case
here.
PR-URL: https://github.com/nodejs/node/pull/30134
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: David Carlier <devnexen@gmail.com>
Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Diffstat (limited to 'src/util.h')
-rw-r--r-- | src/util.h | 45 |
1 files changed, 34 insertions, 11 deletions
diff --git a/src/util.h b/src/util.h index c8bb44721f6..f2d3f355f9f 100644 --- a/src/util.h +++ b/src/util.h @@ -42,6 +42,12 @@ #include <unordered_map> #include <utility> +#ifdef __GNUC__ +#define MUST_USE_RESULT __attribute__((warn_unused_result)) +#else +#define MUST_USE_RESULT +#endif + namespace node { // Maybe remove kPathSeparator when cpp17 is ready @@ -494,14 +500,37 @@ class BufferValue : public MaybeStackBuffer<char> { // silence a compiler warning about that. template <typename T> inline void USE(T&&) {} -// Run a function when exiting the current scope. -struct OnScopeLeave { - std::function<void()> fn_; +template <typename Fn> +struct OnScopeLeaveImpl { + Fn fn_; + bool active_; + + explicit OnScopeLeaveImpl(Fn&& fn) : fn_(std::move(fn)), active_(true) {} + ~OnScopeLeaveImpl() { if (active_) fn_(); } - explicit OnScopeLeave(std::function<void()> fn) : fn_(std::move(fn)) {} - ~OnScopeLeave() { fn_(); } + OnScopeLeaveImpl(const OnScopeLeaveImpl& other) = delete; + OnScopeLeaveImpl& operator=(const OnScopeLeaveImpl& other) = delete; + OnScopeLeaveImpl(OnScopeLeaveImpl&& other) + : fn_(std::move(other.fn_)), active_(other.active_) { + other.active_ = false; + } + OnScopeLeaveImpl& operator=(OnScopeLeaveImpl&& other) { + if (this == &other) return *this; + this->~OnScopeLeave(); + new (this)OnScopeLeaveImpl(std::move(other)); + return *this; + } }; +// Run a function when exiting the current scope. Used like this: +// auto on_scope_leave = OnScopeLeave([&] { +// // ... run some code ... +// }); +template <typename Fn> +inline MUST_USE_RESULT OnScopeLeaveImpl<Fn> OnScopeLeave(Fn&& fn) { + return OnScopeLeaveImpl<Fn>{std::move(fn)}; +} + // Simple RAII wrapper for contiguous data that uses malloc()/free(). template <typename T> struct MallocedBuffer { @@ -679,12 +708,6 @@ constexpr T RoundUp(T a, T b) { return a % b != 0 ? a + b - (a % b) : a; } -#ifdef __GNUC__ -#define MUST_USE_RESULT __attribute__((warn_unused_result)) -#else -#define MUST_USE_RESULT -#endif - class SlicedArguments : public MaybeStackBuffer<v8::Local<v8::Value>> { public: inline explicit SlicedArguments( |