Message ID | 20250729162101.13836-2-laurent.pinchart@ideasonboard.com |
---|---|
State | Superseded |
Headers | show |
Series |
|
Related | show |
Hi 2025. 07. 29. 18:21 keltezéssel, Laurent Pinchart írta: > +template<typename EF> > +class scope_exit > +{ > +public: > + template<typename Fn, > + std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Fn>>, scope_exit> && > + std::is_constructible_v<EF, Fn> && > + !std::is_lvalue_reference_v<Fn>> * = nullptr> I think it should be fine to remove the lvalue condition since we require nothrow constructibility. > + explicit scope_exit(Fn &&fn) > + : exitFunction_(std::forward<Fn>(fn)) > + { > + static_assert(std::is_nothrow_constructible_v<EF, Fn>); > + } > + > + scope_exit(scope_exit &&other) I would probably =delete this until a need arises. > + : exitFunction_(std::move(other.exitFunction_)), > + active_(other.active_) I like std::exchange a lot... so I'd write std::exchange(other.active_, false) Regards, Barnabás Pőcze > + { > + other.release(); > + } > + > + scope_exit(const scope_exit &) = delete; > + > + ~scope_exit() > + { > + if (active_) > + exitFunction_(); > + } > + > + void release() > + { > + active_ = false; > + } > + > +private: > + EF exitFunction_; > + bool active_ = true; > +}; > + > +template<typename EF> > +scope_exit(EF) -> scope_exit<EF>; > +
On Wed, Jul 30, 2025 at 09:58:51AM +0200, Barnabás Pőcze wrote: > 2025. 07. 29. 18:21 keltezéssel, Laurent Pinchart írta: > > +template<typename EF> > > +class scope_exit > > +{ > > +public: > > + template<typename Fn, > > + std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Fn>>, scope_exit> && > > + std::is_constructible_v<EF, Fn> && > > + !std::is_lvalue_reference_v<Fn>> * = nullptr> > > I think it should be fine to remove the lvalue condition since we require > nothrow constructibility. Will be done in v3. > > + explicit scope_exit(Fn &&fn) > > + : exitFunction_(std::forward<Fn>(fn)) > > + { > > + static_assert(std::is_nothrow_constructible_v<EF, Fn>); > > + } > > + > > + scope_exit(scope_exit &&other) > > I would probably =delete this until a need arises. > > > > + : exitFunction_(std::move(other.exitFunction_)), > > + active_(other.active_) > > I like std::exchange a lot... so I'd write > > std::exchange(other.active_, false) Agreed, but I'll instead delete the function :-) > > + { > > + other.release(); > > + } > > + > > + scope_exit(const scope_exit &) = delete; > > + > > + ~scope_exit() > > + { > > + if (active_) > > + exitFunction_(); > > + } > > + > > + void release() > > + { > > + active_ = false; > > + } > > + > > +private: > > + EF exitFunction_; > > + bool active_ = true; > > +}; > > + > > +template<typename EF> > > +scope_exit(EF) -> scope_exit<EF>; > > +
diff --git a/include/libcamera/base/utils.h b/include/libcamera/base/utils.h index 8d5c35782ee3..1d8e5aef9b54 100644 --- a/include/libcamera/base/utils.h +++ b/include/libcamera/base/utils.h @@ -428,6 +428,51 @@ private: std::vector<std::function<void()>> actions_; }; +#ifndef __DOXYGEN__ +template<typename EF> +class scope_exit +{ +public: + template<typename Fn, + std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Fn>>, scope_exit> && + std::is_constructible_v<EF, Fn> && + !std::is_lvalue_reference_v<Fn>> * = nullptr> + explicit scope_exit(Fn &&fn) + : exitFunction_(std::forward<Fn>(fn)) + { + static_assert(std::is_nothrow_constructible_v<EF, Fn>); + } + + scope_exit(scope_exit &&other) + : exitFunction_(std::move(other.exitFunction_)), + active_(other.active_) + { + other.release(); + } + + scope_exit(const scope_exit &) = delete; + + ~scope_exit() + { + if (active_) + exitFunction_(); + } + + void release() + { + active_ = false; + } + +private: + EF exitFunction_; + bool active_ = true; +}; + +template<typename EF> +scope_exit(EF) -> scope_exit<EF>; + +#endif /* __DOXYGEN__ */ + } /* namespace utils */ #ifndef __DOXYGEN__
The scope_exit class is an implementation of the identically named C++ library fundamentals TS v3 class, as documented in [1]. It is a simpler version of the libcamera-specific ScopeExitActions class and doesn't require dynamic heap memory allocation, making it more suitable for hot paths. The class is not documented as it implements a C++ standard (even if experimental) API. [1] https://en.cppreference.com/w/cpp/experimental/scope_exit/scope_exit.html Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> --- I have named the class scope_exit instead of ScopeExit to match the C++ library fundamentals TS v3 class, and have not documented it as it's meant as an implementation of the standard. It is however not clear if and when scope_exit would become part of a ratified C++ standard, so I'm open to instead create a libcamera-specific ScopeExit class and document it. --- include/libcamera/base/utils.h | 45 ++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) -- Regards, Laurent Pinchart