forked from OSchip/llvm-project
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
|