This commit reverts 5aaefa51 (and also partly 7f285f48e77 and b6d75682f9, which were related to the original commit). As landed, 5aaefa51 had unintended consequences on some downstream bots and didn't have proper coverage upstream due to a few subtle things. Implementing this is something we should do in libc++, however we'll first need to address a few issues listed in https://reviews.llvm.org/D106124#3349710. Differential Revision: https://reviews.llvm.org/D120683
92 lines
3.0 KiB
C++
92 lines
3.0 KiB
C++
//===----------------------------------------------------------------------===//
|
|
//
|
|
// 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
|