diff options
Diffstat (limited to 'contrib/llvm-project/libcxx/include/__utility/transaction.h')
-rw-r--r-- | contrib/llvm-project/libcxx/include/__utility/transaction.h | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/contrib/llvm-project/libcxx/include/__utility/transaction.h b/contrib/llvm-project/libcxx/include/__utility/transaction.h new file mode 100644 index 000000000000..87e51c0b198e --- /dev/null +++ b/contrib/llvm-project/libcxx/include/__utility/transaction.h @@ -0,0 +1,91 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___UTILITY_TRANSACTION_H +#define _LIBCPP___UTILITY_TRANSACTION_H + +#include <__config> +#include <__utility/exchange.h> +#include <__utility/move.h> +#include <type_traits> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +// __transaction 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 +// they can be moved around for convenience. +// +// __transaction can help greatly simplify code that would normally be cluttered by +// `#if _LIBCPP_NO_EXCEPTIONS`. For example: +// +// template <class Iterator, class Size, class OutputIterator> +// Iterator uninitialized_copy_n(Iterator iter, Size n, OutputIterator out) { +// typedef typename iterator_traits<Iterator>::value_type value_type; +// __transaction transaction([start=out, &out] { +// std::destroy(start, out); +// }); +// +// for (; n > 0; ++iter, ++out, --n) { +// ::new ((void*)std::addressof(*out)) value_type(*iter); +// } +// transaction.__complete(); +// return out; +// } +// +template <class _Rollback> +struct __transaction { + __transaction() = delete; + + _LIBCPP_HIDE_FROM_ABI + _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit __transaction(_Rollback __rollback) + : __rollback_(_VSTD::move(__rollback)) + , __completed_(false) + { } + + _LIBCPP_HIDE_FROM_ABI + _LIBCPP_CONSTEXPR_AFTER_CXX17 __transaction(__transaction&& __other) + _NOEXCEPT_(is_nothrow_move_constructible<_Rollback>::value) + : __rollback_(_VSTD::move(__other.__rollback_)) + , __completed_(__other.__completed_) + { + __other.__completed_ = true; + } + + __transaction(__transaction const&) = delete; + __transaction& operator=(__transaction const&) = delete; + __transaction& operator=(__transaction&&) = delete; + + _LIBCPP_HIDE_FROM_ABI + _LIBCPP_CONSTEXPR_AFTER_CXX17 void __complete() _NOEXCEPT { + __completed_ = true; + } + + _LIBCPP_HIDE_FROM_ABI + _LIBCPP_CONSTEXPR_AFTER_CXX17 ~__transaction() { + if (!__completed_) + __rollback_(); + } + +private: + _Rollback __rollback_; + bool __completed_; +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___UTILITY_TRANSACTION_H |