123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560 |
- #ifndef BOOST_SCOPE_SCOPE_EXIT_HPP_INCLUDED_
- #define BOOST_SCOPE_SCOPE_EXIT_HPP_INCLUDED_
- #include <type_traits>
- #include <boost/scope/detail/config.hpp>
- #include <boost/scope/detail/is_not_like.hpp>
- #include <boost/scope/detail/compact_storage.hpp>
- #include <boost/scope/detail/move_or_copy_construct_ref.hpp>
- #include <boost/scope/detail/is_nonnull_default_constructible.hpp>
- #include <boost/scope/detail/type_traits/conjunction.hpp>
- #include <boost/scope/detail/type_traits/is_invocable.hpp>
- #include <boost/scope/detail/type_traits/is_nothrow_invocable.hpp>
- #include <boost/scope/detail/header.hpp>
- #ifdef BOOST_HAS_PRAGMA_ONCE
- #pragma once
- #endif
- namespace boost {
- namespace scope {
- template< typename Func, typename Cond >
- class scope_exit;
- namespace detail {
- template< typename T >
- using is_not_like_scope_exit = detail::is_not_like< T, scope_exit >;
- template< typename Func, typename Cond >
- class init_guard
- {
- private:
- Func& m_func;
- Cond& m_cond;
- bool m_active;
- public:
- init_guard(Func& func, Cond& cond, bool active) noexcept :
- m_func(func),
- m_cond(cond),
- m_active(active)
- {
- }
- init_guard(init_guard const&) = delete;
- init_guard& operator= (init_guard const&) = delete;
- ~init_guard()
- noexcept(detail::conjunction<
- detail::is_nothrow_invocable< Func& >,
- detail::is_nothrow_invocable< Cond& >
- >::value)
- {
- if (m_active && m_cond())
- m_func();
- }
- Func&& get_func() noexcept
- {
- return static_cast< Func&& >(m_func);
- }
- Cond&& get_cond() noexcept
- {
- return static_cast< Cond&& >(m_cond);
- }
- void deactivate() noexcept
- {
- m_active = false;
- }
- };
- }
- class always_true
- {
- public:
-
- using result_type = bool;
-
- result_type operator()() const noexcept
- {
- return true;
- }
- };
- template< typename Func, typename Cond = always_true >
- class scope_exit
- {
- private:
- struct func_holder :
- public detail::compact_storage< Func >
- {
- using func_base = detail::compact_storage< Func >;
- template<
- typename F,
- typename C,
- typename = typename std::enable_if< std::is_constructible< Func, F >::value >::type
- >
- explicit func_holder(F&& func, C&& cond, bool active, std::true_type) noexcept :
- func_base(static_cast< F&& >(func))
- {
- }
- template<
- typename F,
- typename C,
- typename = typename std::enable_if< std::is_constructible< Func, F >::value >::type
- >
- explicit func_holder(F&& func, C&& cond, bool active, std::false_type) :
- func_holder(detail::init_guard< F, C >(func, cond, active))
- {
- }
- private:
- template< typename F, typename C >
- explicit func_holder(detail::init_guard< F, C >&& init) :
- func_base(init.get_func())
- {
- init.deactivate();
- }
- };
- struct cond_holder :
- public detail::compact_storage< Cond >
- {
- using cond_base = detail::compact_storage< Cond >;
- template<
- typename C,
- typename = typename std::enable_if< std::is_constructible< Cond, C >::value >::type
- >
- explicit cond_holder(C&& cond, Func& func, bool active, std::true_type) noexcept :
- cond_base(static_cast< C&& >(cond))
- {
- }
- template<
- typename C,
- typename = typename std::enable_if< std::is_constructible< Cond, C >::value >::type
- >
- explicit cond_holder(C&& cond, Func& func, bool active, std::false_type) :
- cond_holder(detail::init_guard< Func&, C >(func, cond, active))
- {
- }
- private:
- template< typename C >
- explicit cond_holder(detail::init_guard< Func&, C >&& init) :
- cond_base(init.get_cond())
- {
- init.deactivate();
- }
- };
- struct data :
- public func_holder,
- public cond_holder
- {
- bool m_active;
- template<
- typename F,
- typename C,
- typename = typename std::enable_if< detail::conjunction<
- std::is_constructible< func_holder, F, C, bool, typename std::is_nothrow_constructible< Func, F >::type >,
- std::is_constructible< cond_holder, C, Func&, bool, typename std::is_nothrow_constructible< Cond, C >::type >
- >::value >::type
- >
- explicit data(F&& func, C&& cond, bool active)
- noexcept(detail::conjunction< std::is_nothrow_constructible< Func, F >, std::is_nothrow_constructible< Cond, C > >::value) :
- func_holder(static_cast< F&& >(func), static_cast< C&& >(cond), active, typename std::is_nothrow_constructible< Func, F >::type()),
- cond_holder(static_cast< C&& >(cond), func_holder::get(), active, typename std::is_nothrow_constructible< Cond, C >::type()),
- m_active(active)
- {
- }
- Func& get_func() noexcept
- {
- return func_holder::get();
- }
- Func const& get_func() const noexcept
- {
- return func_holder::get();
- }
- Cond& get_cond() noexcept
- {
- return cond_holder::get();
- }
- Cond const& get_cond() const noexcept
- {
- return cond_holder::get();
- }
- bool deactivate() noexcept
- {
- bool active = m_active;
- m_active = false;
- return active;
- }
- };
- data m_data;
- public:
-
- template<
- typename F
-
- , typename = typename std::enable_if< detail::conjunction<
- detail::is_nothrow_nonnull_default_constructible< Cond >,
- std::is_constructible<
- data,
- typename detail::move_or_copy_construct_ref< F, Func >::type,
- typename detail::move_or_copy_construct_ref< Cond >::type,
- bool
- >,
- detail::is_not_like_scope_exit< F >
- >::value >::type
-
- >
- explicit scope_exit(F&& func, bool active = true)
- noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(
- std::is_nothrow_constructible<
- data,
- typename detail::move_or_copy_construct_ref< F, Func >::type,
- typename detail::move_or_copy_construct_ref< Cond >::type,
- bool
- >::value
- )) :
- m_data
- (
- static_cast< typename detail::move_or_copy_construct_ref< F, Func >::type >(func),
- static_cast< typename detail::move_or_copy_construct_ref< Cond >::type >(Cond()),
- active
- )
- {
- }
-
- template<
- typename F,
- typename C
-
- , typename = typename std::enable_if< detail::conjunction<
- detail::is_invocable< C const& >,
- std::is_constructible<
- data,
- typename detail::move_or_copy_construct_ref< F, Func >::type,
- typename detail::move_or_copy_construct_ref< C, Cond >::type,
- bool
- >
- >::value >::type
-
- >
- explicit scope_exit(F&& func, C&& cond, bool active = true)
- noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(
- std::is_nothrow_constructible<
- data,
- typename detail::move_or_copy_construct_ref< F, Func >::type,
- typename detail::move_or_copy_construct_ref< C, Cond >::type,
- bool
- >::value
- )) :
- m_data
- (
- static_cast< typename detail::move_or_copy_construct_ref< F, Func >::type >(func),
- static_cast< typename detail::move_or_copy_construct_ref< C, Cond >::type >(cond),
- active
- )
- {
- }
-
-
- template<
- bool Requires = std::is_constructible<
- data,
- typename detail::move_or_copy_construct_ref< Func >::type,
- typename detail::move_or_copy_construct_ref< Cond >::type,
- bool
- >::value,
- typename = typename std::enable_if< Requires >::type
- >
-
- scope_exit(scope_exit&& that)
- noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(
- std::is_nothrow_constructible<
- data,
- typename detail::move_or_copy_construct_ref< Func >::type,
- typename detail::move_or_copy_construct_ref< Cond >::type,
- bool
- >::value
- )) :
- m_data
- (
- static_cast< typename detail::move_or_copy_construct_ref< Func >::type >(that.m_data.get_func()),
- static_cast< typename detail::move_or_copy_construct_ref< Cond >::type >(that.m_data.get_cond()),
- that.m_data.deactivate()
- )
- {
- }
- scope_exit& operator= (scope_exit&&) = delete;
- scope_exit(scope_exit const&) = delete;
- scope_exit& operator= (scope_exit const&) = delete;
-
- ~scope_exit()
- noexcept(BOOST_SCOPE_DETAIL_DOC_HIDDEN(
- detail::conjunction<
- detail::is_nothrow_invocable< Func& >,
- detail::is_nothrow_invocable< Cond& >
- >::value
- ))
- {
- if (BOOST_LIKELY(m_data.m_active && m_data.get_cond()()))
- m_data.get_func()();
- }
-
- bool active() const noexcept
- {
- return m_data.m_active;
- }
-
- void set_active(bool active) noexcept
- {
- m_data.m_active = active;
- }
- };
- #if !defined(BOOST_NO_CXX17_DEDUCTION_GUIDES)
- template< typename Func >
- explicit scope_exit(Func) -> scope_exit< Func >;
- template< typename Func >
- explicit scope_exit(Func, bool) -> scope_exit< Func >;
- template< typename Func, typename Cond >
- explicit scope_exit(Func, Cond) -> scope_exit< Func, Cond >;
- template< typename Func, typename Cond >
- explicit scope_exit(Func, Cond, bool) -> scope_exit< Func, Cond >;
- #endif
- template< typename F >
- inline scope_exit< typename std::decay< F >::type > make_scope_exit(F&& func, bool active = true)
- noexcept(std::is_nothrow_constructible<
- scope_exit< typename std::decay< F >::type >,
- F,
- bool
- >::value)
- {
- return scope_exit< typename std::decay< F >::type >(static_cast< F&& >(func), active);
- }
- template< typename F, typename C >
- inline
- #if !defined(BOOST_SCOPE_DOXYGEN)
- typename std::enable_if<
- std::is_constructible<
- scope_exit< typename std::decay< F >::type, typename std::decay< C >::type >,
- F,
- C,
- bool
- >::value,
- scope_exit< typename std::decay< F >::type, typename std::decay< C >::type >
- >::type
- #else
- scope_exit< typename std::decay< F >::type, typename std::decay< C >::type >
- #endif
- make_scope_exit(F&& func, C&& cond, bool active = true)
- noexcept(std::is_nothrow_constructible<
- scope_exit< typename std::decay< F >::type, typename std::decay< C >::type >,
- F,
- C,
- bool
- >::value)
- {
- return scope_exit< typename std::decay< F >::type, typename std::decay< C >::type >(static_cast< F&& >(func), static_cast< C&& >(cond), active);
- }
- }
- }
- #include <boost/scope/detail/footer.hpp>
- #endif
|