diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -678,6 +678,7 @@ __utility/cmp.h __utility/convert_to_integral.h __utility/declval.h + __utility/exception_guard.h __utility/exchange.h __utility/forward.h __utility/forward_like.h @@ -690,7 +691,6 @@ __utility/rel_ops.h __utility/swap.h __utility/to_underlying.h - __utility/transaction.h __utility/unreachable.h __variant/monostate.h __verbose_abort diff --git a/libcxx/include/__memory/uninitialized_algorithms.h b/libcxx/include/__memory/uninitialized_algorithms.h --- a/libcxx/include/__memory/uninitialized_algorithms.h +++ b/libcxx/include/__memory/uninitialized_algorithms.h @@ -21,9 +21,9 @@ #include <__memory/pointer_traits.h> #include <__memory/voidify.h> #include <__type_traits/is_constant_evaluated.h> +#include <__utility/exception_guard.h> #include <__utility/move.h> #include <__utility/pair.h> -#include <__utility/transaction.h> #include #include @@ -412,7 +412,10 @@ _Tp& __array = *__loc; // If an exception is thrown, destroy what we have constructed so far in reverse order. - __transaction __guard([&]() { std::__allocator_destroy_multidimensional(__elem_alloc, __array, __array + __i); }); + __exception_guard __guard([&]() { + std::__allocator_destroy_multidimensional(__elem_alloc, __array, __array + __i); + }); + for (; __i != extent_v<_Tp>; ++__i) { std::__allocator_construct_at(__elem_alloc, std::addressof(__array[__i])); } @@ -449,7 +452,9 @@ _Tp& __array = *__loc; // If an exception is thrown, destroy what we have constructed so far in reverse order. - __transaction __guard([&]() { std::__allocator_destroy_multidimensional(__elem_alloc, __array, __array + __i); }); + __exception_guard __guard([&]() { + std::__allocator_destroy_multidimensional(__elem_alloc, __array, __array + __i); + }); for (; __i != extent_v<_Tp>; ++__i) { std::__allocator_construct_at(__elem_alloc, std::addressof(__array[__i]), __arg[__i]); } @@ -474,7 +479,7 @@ _BidirIter __begin = __it; // If an exception is thrown, destroy what we have constructed so far in reverse order. - __transaction __guard([&]() { std::__allocator_destroy_multidimensional(__value_alloc, __begin, __it); }); + __exception_guard __guard([&]() { std::__allocator_destroy_multidimensional(__value_alloc, __begin, __it); }); for (; __n != 0; --__n, ++__it) { std::__allocator_construct_at(__value_alloc, std::addressof(*__it), __value); } @@ -491,7 +496,7 @@ _BidirIter __begin = __it; // If an exception is thrown, destroy what we have constructed so far in reverse order. - __transaction __guard([&]() { std::__allocator_destroy_multidimensional(__value_alloc, __begin, __it); }); + __exception_guard __guard([&]() { std::__allocator_destroy_multidimensional(__value_alloc, __begin, __it); }); for (; __n != 0; --__n, ++__it) { std::__allocator_construct_at(__value_alloc, std::addressof(*__it)); } @@ -532,21 +537,15 @@ template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter2 __uninitialized_allocator_copy(_Alloc& __alloc, _Iter1 __first1, _Sent1 __last1, _Iter2 __first2) { -#ifndef _LIBCPP_NO_EXCEPTIONS auto __destruct_first = __first2; - try { -#endif + auto __guard = + std::__make_exception_guard(_AllocatorDestroyRangeReverse<_Alloc, _Iter2>(__alloc, __destruct_first, __first2)); while (__first1 != __last1) { allocator_traits<_Alloc>::construct(__alloc, std::__to_address(__first2), *__first1); ++__first1; ++__first2; } -#ifndef _LIBCPP_NO_EXCEPTIONS - } catch (...) { - _AllocatorDestroyRangeReverse<_Alloc, _Iter2>(__alloc, __destruct_first, __first2)(); - throw; - } -#endif + __guard.__complete(); return __first2; } @@ -588,10 +587,9 @@ _Alloc& __alloc, _Iter1 __first1, _Sent1 __last1, _Iter2 __first2) { static_assert(__is_cpp17_move_insertable<_Alloc>::value, "The specified type does not meet the requirements of Cpp17MoveInsertable"); -#ifndef _LIBCPP_NO_EXCEPTIONS auto __destruct_first = __first2; - try { -#endif + auto __guard = + std::__make_exception_guard(_AllocatorDestroyRangeReverse<_Alloc, _Iter2>(__alloc, __destruct_first, __first2)); while (__first1 != __last1) { #ifndef _LIBCPP_NO_EXCEPTIONS allocator_traits<_Alloc>::construct(__alloc, std::__to_address(__first2), std::move_if_noexcept(*__first1)); @@ -601,12 +599,7 @@ ++__first1; ++__first2; } -#ifndef _LIBCPP_NO_EXCEPTIONS - } catch (...) { - _AllocatorDestroyRangeReverse<_Alloc, _Iter2>(__alloc, __destruct_first, __first2)(); - throw; - } -#endif + __guard.__complete(); return __first2; } diff --git a/libcxx/include/__memory_resource/polymorphic_allocator.h b/libcxx/include/__memory_resource/polymorphic_allocator.h --- a/libcxx/include/__memory_resource/polymorphic_allocator.h +++ b/libcxx/include/__memory_resource/polymorphic_allocator.h @@ -12,7 +12,7 @@ #include <__assert> #include <__config> #include <__memory_resource/memory_resource.h> -#include <__utility/transaction.h> +#include <__utility/exception_guard.h> #include #include #include @@ -98,7 +98,7 @@ template [[nodiscard]] _Type* new_object(_CtorArgs&&... __ctor_args) { _Type* __ptr = allocate_object<_Type>(); - __transaction __guard([&] { deallocate_object(__ptr); }); + __exception_guard __guard([&] { deallocate_object(__ptr); }); construct(__ptr, std::forward<_CtorArgs>(__ctor_args)...); __guard.__complete(); return __ptr; diff --git a/libcxx/include/__utility/transaction.h b/libcxx/include/__utility/exception_guard.h rename from libcxx/include/__utility/transaction.h rename to libcxx/include/__utility/exception_guard.h --- a/libcxx/include/__utility/transaction.h +++ b/libcxx/include/__utility/exception_guard.h @@ -20,45 +20,47 @@ _LIBCPP_BEGIN_NAMESPACE_STD -// __transaction is a helper class for writing code with the strong exception guarantee. +// __exception_guard is a helper class for writing code with the strong exception guarantee. // // When writing code that can throw an exception, one can store rollback instructions in a // transaction so that if an exception is thrown at any point during the lifetime of the // transaction, it will be rolled back automatically. When the transaction is done, one // must mark it as being complete so it isn't rolled back when the transaction is destroyed. // -// Transactions are not default constructible, they can't be copied or assigned to, but +// Exception guards are not default constructible, they can't be copied or assigned to, but // they can be moved around for convenience. // -// __transaction can help greatly simplify code that would normally be cluttered by +// __exception_guard can help greatly simplify code that would normally be cluttered by // `#if _LIBCPP_NO_EXCEPTIONS`. For example: // // template // Iterator uninitialized_copy_n(Iterator iter, Size n, OutputIterator out) { // typedef typename iterator_traits::value_type value_type; -// __transaction transaction([start=out, &out] { +// __exception_guard guard([start=out, &out] { // std::destroy(start, out); // }); // // for (; n > 0; ++iter, ++out, --n) { // ::new ((void*)std::addressof(*out)) value_type(*iter); // } -// transaction.__complete(); +// guard.__complete(); // return out; // } // + +#ifndef _LIBCPP_NO_EXCEPTIONS template -struct __transaction { - __transaction() = delete; +struct __exception_guard { + __exception_guard() = delete; _LIBCPP_HIDE_FROM_ABI - _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit __transaction(_Rollback __rollback) + _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit __exception_guard(_Rollback __rollback) : __rollback_(_VSTD::move(__rollback)) , __completed_(false) { } _LIBCPP_HIDE_FROM_ABI - _LIBCPP_CONSTEXPR_SINCE_CXX20 __transaction(__transaction&& __other) + _LIBCPP_CONSTEXPR_SINCE_CXX20 __exception_guard(__exception_guard&& __other) _NOEXCEPT_(is_nothrow_move_constructible<_Rollback>::value) : __rollback_(_VSTD::move(__other.__rollback_)) , __completed_(__other.__completed_) @@ -66,9 +68,9 @@ __other.__completed_ = true; } - __transaction(__transaction const&) = delete; - __transaction& operator=(__transaction const&) = delete; - __transaction& operator=(__transaction&&) = delete; + __exception_guard(__exception_guard const&) = delete; + __exception_guard& operator=(__exception_guard const&) = delete; + __exception_guard& operator=(__exception_guard&&) = delete; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __complete() _NOEXCEPT { @@ -76,7 +78,7 @@ } _LIBCPP_HIDE_FROM_ABI - _LIBCPP_CONSTEXPR_SINCE_CXX20 ~__transaction() { + _LIBCPP_CONSTEXPR_SINCE_CXX20 ~__exception_guard() { if (!__completed_) __rollback_(); } @@ -85,11 +87,35 @@ _Rollback __rollback_; bool __completed_; }; -_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(__transaction); +#else // _LIBCPP_NO_EXCEPTIONS +template +struct __exception_guard { + __exception_guard() = delete; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NODEBUG __exception_guard(_Rollback) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NODEBUG __exception_guard(__exception_guard&&) + _NOEXCEPT_(is_nothrow_move_constructible<_Rollback>::value) {} + __exception_guard(__exception_guard const&) = delete; + __exception_guard& operator=(__exception_guard const&) = delete; + __exception_guard& operator=(__exception_guard&&) = delete; + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NODEBUG void __complete() _NOEXCEPT { + __completed_ = true; + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NODEBUG ~__exception_guard() { + _LIBCPP_ASSERT(__completed_, "__exception_guard not completed with exceptions disabled"); + } + +private: + bool __completed_ = false; +}; +#endif // _LIBCPP_NO_EXCEPTIONS + +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(__exception_guard); template -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __transaction<_Rollback> __make_transaction(_Rollback __rollback) { - return __transaction<_Rollback>(std::move(__rollback)); +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __exception_guard<_Rollback> __make_exception_guard(_Rollback __rollback) { + return __exception_guard<_Rollback>(std::move(__rollback)); } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in --- a/libcxx/include/module.modulemap.in +++ b/libcxx/include/module.modulemap.in @@ -1505,6 +1505,7 @@ module cmp { private header "__utility/cmp.h" } module convert_to_integral { private header "__utility/convert_to_integral.h" } module declval { private header "__utility/declval.h" } + module exception_guard { private header "__utility/exception_guard.h" } module exchange { private header "__utility/exchange.h" } module forward { private header "__utility/forward.h" } module forward_like { private header "__utility/forward_like.h" } @@ -1518,7 +1519,6 @@ module rel_ops { private header "__utility/rel_ops.h" } module swap { private header "__utility/swap.h" } module to_underlying { private header "__utility/to_underlying.h" } - module transaction { private header "__utility/transaction.h" } module unreachable { private header "__utility/unreachable.h" } } } diff --git a/libcxx/include/utility b/libcxx/include/utility --- a/libcxx/include/utility +++ b/libcxx/include/utility @@ -243,6 +243,7 @@ #include <__utility/auto_cast.h> #include <__utility/cmp.h> #include <__utility/declval.h> +#include <__utility/exception_guard.h> #include <__utility/exchange.h> #include <__utility/forward.h> #include <__utility/forward_like.h> @@ -255,7 +256,6 @@ #include <__utility/rel_ops.h> #include <__utility/swap.h> #include <__utility/to_underlying.h> -#include <__utility/transaction.h> #include <__utility/unreachable.h> #include #include diff --git a/libcxx/include/vector b/libcxx/include/vector --- a/libcxx/include/vector +++ b/libcxx/include/vector @@ -299,10 +299,10 @@ #include <__split_buffer> #include <__type_traits/is_allocator.h> #include <__type_traits/noexcept_move_assign_container.h> +#include <__utility/exception_guard.h> #include <__utility/forward.h> #include <__utility/move.h> #include <__utility/swap.h> -#include <__utility/transaction.h> #include #include #include @@ -1064,7 +1064,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(size_type __n) { - auto __guard = std::__make_transaction(__destroy_vector(*this)); + auto __guard = std::__make_exception_guard(__destroy_vector(*this)); std::__debug_db_insert_c(this); if (__n > 0) { @@ -1080,7 +1080,7 @@ vector<_Tp, _Allocator>::vector(size_type __n, const allocator_type& __a) : __end_cap_(nullptr, __a) { - auto __guard = std::__make_transaction(__destroy_vector(*this)); + auto __guard = std::__make_exception_guard(__destroy_vector(*this)); std::__debug_db_insert_c(this); if (__n > 0) { @@ -1095,7 +1095,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(size_type __n, const value_type& __x) { - auto __guard = std::__make_transaction(__destroy_vector(*this)); + auto __guard = std::__make_exception_guard(__destroy_vector(*this)); std::__debug_db_insert_c(this); if (__n > 0) { @@ -1112,7 +1112,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(_InputIterator __first, _InputIterator __last) { - auto __guard = std::__make_transaction(__destroy_vector(*this)); + auto __guard = std::__make_exception_guard(__destroy_vector(*this)); std::__debug_db_insert_c(this); for (; __first != __last; ++__first) emplace_back(*__first); @@ -1127,7 +1127,7 @@ vector<_Tp, _Allocator>::vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a) : __end_cap_(nullptr, __a) { - auto __guard = std::__make_transaction(__destroy_vector(*this)); + auto __guard = std::__make_exception_guard(__destroy_vector(*this)); std::__debug_db_insert_c(this); for (; __first != __last; ++__first) emplace_back(*__first); @@ -1141,7 +1141,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(_ForwardIterator __first, _ForwardIterator __last) { - auto __guard = std::__make_transaction(__destroy_vector(*this)); + auto __guard = std::__make_exception_guard(__destroy_vector(*this)); std::__debug_db_insert_c(this); size_type __n = static_cast(std::distance(__first, __last)); if (__n > 0) @@ -1160,7 +1160,7 @@ vector<_Tp, _Allocator>::vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a) : __end_cap_(nullptr, __a) { - auto __guard = std::__make_transaction(__destroy_vector(*this)); + auto __guard = std::__make_exception_guard(__destroy_vector(*this)); std::__debug_db_insert_c(this); size_type __n = static_cast(std::distance(__first, __last)); if (__n > 0) @@ -1176,7 +1176,7 @@ vector<_Tp, _Allocator>::vector(const vector& __x) : __end_cap_(nullptr, __alloc_traits::select_on_container_copy_construction(__x.__alloc())) { - auto __guard = std::__make_transaction(__destroy_vector(*this)); + auto __guard = std::__make_exception_guard(__destroy_vector(*this)); std::__debug_db_insert_c(this); size_type __n = __x.size(); if (__n > 0) @@ -1192,7 +1192,7 @@ vector<_Tp, _Allocator>::vector(const vector& __x, const __type_identity_t& __a) : __end_cap_(nullptr, __a) { - auto __guard = std::__make_transaction(__destroy_vector(*this)); + auto __guard = std::__make_exception_guard(__destroy_vector(*this)); std::__debug_db_insert_c(this); size_type __n = __x.size(); if (__n > 0) @@ -1240,7 +1240,7 @@ else { typedef move_iterator _Ip; - auto __guard = std::__make_transaction(__destroy_vector(*this)); + auto __guard = std::__make_exception_guard(__destroy_vector(*this)); assign(_Ip(__x.begin()), _Ip(__x.end())); __guard.__complete(); } @@ -1253,7 +1253,7 @@ inline _LIBCPP_HIDE_FROM_ABI vector<_Tp, _Allocator>::vector(initializer_list __il) { - auto __guard = std::__make_transaction(__destroy_vector(*this)); + auto __guard = std::__make_exception_guard(__destroy_vector(*this)); std::__debug_db_insert_c(this); if (__il.size() > 0) { @@ -1269,7 +1269,7 @@ vector<_Tp, _Allocator>::vector(initializer_list __il, const allocator_type& __a) : __end_cap_(nullptr, __a) { - auto __guard = std::__make_transaction(__destroy_vector(*this)); + auto __guard = std::__make_exception_guard(__destroy_vector(*this)); std::__debug_db_insert_c(this); if (__il.size() > 0) { @@ -2648,7 +2648,7 @@ __size_(0), __cap_alloc_(0, __default_init_tag()) { - auto __guard = std::__make_transaction(__destroy_vector(*this)); + auto __guard = std::__make_exception_guard(__destroy_vector(*this)); size_type __n = static_cast(std::distance(__first, __last)); if (__n > 0) { @@ -2667,7 +2667,7 @@ __size_(0), __cap_alloc_(0, static_cast<__storage_allocator>(__a)) { - auto __guard = std::__make_transaction(__destroy_vector(*this)); + auto __guard = std::__make_exception_guard(__destroy_vector(*this)); size_type __n = static_cast(std::distance(__first, __last)); if (__n > 0) { diff --git a/libcxx/test/libcxx/private_headers.verify.cpp b/libcxx/test/libcxx/private_headers.verify.cpp --- a/libcxx/test/libcxx/private_headers.verify.cpp +++ b/libcxx/test/libcxx/private_headers.verify.cpp @@ -690,6 +690,7 @@ #include <__utility/cmp.h> // expected-error@*:* {{use of private header from outside its module: '__utility/cmp.h'}} #include <__utility/convert_to_integral.h> // expected-error@*:* {{use of private header from outside its module: '__utility/convert_to_integral.h'}} #include <__utility/declval.h> // expected-error@*:* {{use of private header from outside its module: '__utility/declval.h'}} +#include <__utility/exception_guard.h> // expected-error@*:* {{use of private header from outside its module: '__utility/exception_guard.h'}} #include <__utility/exchange.h> // expected-error@*:* {{use of private header from outside its module: '__utility/exchange.h'}} #include <__utility/forward.h> // expected-error@*:* {{use of private header from outside its module: '__utility/forward.h'}} #include <__utility/forward_like.h> // expected-error@*:* {{use of private header from outside its module: '__utility/forward_like.h'}} @@ -702,7 +703,6 @@ #include <__utility/rel_ops.h> // expected-error@*:* {{use of private header from outside its module: '__utility/rel_ops.h'}} #include <__utility/swap.h> // expected-error@*:* {{use of private header from outside its module: '__utility/swap.h'}} #include <__utility/to_underlying.h> // expected-error@*:* {{use of private header from outside its module: '__utility/to_underlying.h'}} -#include <__utility/transaction.h> // expected-error@*:* {{use of private header from outside its module: '__utility/transaction.h'}} #include <__utility/unreachable.h> // expected-error@*:* {{use of private header from outside its module: '__utility/unreachable.h'}} #include <__variant/monostate.h> // expected-error@*:* {{use of private header from outside its module: '__variant/monostate.h'}} // GENERATED-MARKER diff --git a/libcxx/test/libcxx/utilities/exception_guard.no_exceptions.pass.cpp b/libcxx/test/libcxx/utilities/exception_guard.no_exceptions.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/utilities/exception_guard.no_exceptions.pass.cpp @@ -0,0 +1,23 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03 + +// ADDITIONAL_COMPILE_FLAGS: -fno-exceptions -D_LIBCPP_ENABLE_ASSERTIONS + +#include "check_assertion.h" +#include "test_macros.h" + +TEST_DIAGNOSTIC_PUSH +TEST_CLANG_DIAGNOSTIC_IGNORED("-Wprivate-header") +#include <__utility/exception_guard.h> +TEST_DIAGNOSTIC_POP + +int main(int, char**) { + TEST_LIBCPP_ASSERT_FAILURE(std::__make_exception_guard([] {}), "__exception_guard not completed with exceptions disabled"); +} diff --git a/libcxx/test/libcxx/utilities/transaction.pass.cpp b/libcxx/test/libcxx/utilities/exception_guard.pass.cpp rename from libcxx/test/libcxx/utilities/transaction.pass.cpp rename to libcxx/test/libcxx/utilities/exception_guard.pass.cpp --- a/libcxx/test/libcxx/utilities/transaction.pass.cpp +++ b/libcxx/test/libcxx/utilities/exception_guard.pass.cpp @@ -8,7 +8,8 @@ // UNSUPPORTED: c++03 -#include // for __transaction +// UNSUPPORTED: no-exceptions + #include #include #include @@ -22,7 +23,7 @@ bool rolled_back = false; { auto rollback = [&] { rolled_back = true; }; - std::__transaction t(rollback); + std::__exception_guard g(rollback); } assert(rolled_back); } @@ -33,8 +34,8 @@ bool rolled_back = false; { auto rollback = [&] { rolled_back = true; }; - std::__transaction t(rollback); - t.__complete(); + std::__exception_guard g(rollback); + g.__complete(); } assert(!rolled_back); } @@ -47,8 +48,8 @@ int rollbacks = 0; { auto rollback = [&] { ++rollbacks; }; - std::__transaction t(rollback); - auto other = std::move(t); + std::__exception_guard g(rollback); + auto other = std::move(g); } assert(rollbacks == 1); } @@ -58,8 +59,8 @@ int rollbacks = 0; { auto rollback = [&] { ++rollbacks; }; - std::__transaction t(rollback); - auto other = std::move(t); + std::__exception_guard g(rollback); + auto other = std::move(g); other.__complete(); } assert(rollbacks == 0); @@ -69,7 +70,7 @@ // Basic properties of the type { struct Rollback { void operator()() const { } }; - using Transaction = std::__transaction; + using Transaction = std::__exception_guard; static_assert(!std::is_default_constructible::value, ""); @@ -85,7 +86,7 @@ ThrowOnMove(ThrowOnMove&&) noexcept(false) { } void operator()() const { } }; - using ThrowOnMoveTransaction = std::__transaction; + using ThrowOnMoveTransaction = std::__exception_guard; ASSERT_NOEXCEPT(std::declval().__complete()); static_assert( std::is_nothrow_move_constructible::value, ""); @@ -104,7 +105,7 @@ bool rolled_back = false; auto rollback = [&] { rolled_back = true; }; try { - std::__transaction t(rollback); + std::__exception_guard g(rollback); throw 0; } catch (...) { } assert(rolled_back); @@ -116,14 +117,14 @@ bool rolled_back = false; auto rollback = [&] { rolled_back = true; }; try { - std::__transaction t(rollback); - t.__complete(); + std::__exception_guard g(rollback); + g.__complete(); throw 0; } catch (...) { } assert(!rolled_back); } - // Make sure __transaction does not rollback if the transaction is marked as + // Make sure __exception_guard does not rollback if the transaction is marked as // completed within a destructor. { struct S { @@ -131,8 +132,8 @@ ~S() { auto rollback = [this]{ x_ = true; }; - std::__transaction t(rollback); - t.__complete(); + std::__exception_guard g(rollback); + g.__complete(); } bool& x_;