diff options
author | Marco Bubke <marco.bubke@qt.io> | 2018-02-05 11:23:36 +0100 |
---|---|---|
committer | Marco Bubke <marco.bubke@qt.io> | 2018-02-14 15:03:22 +0000 |
commit | dfb9e4355f14afd9b543b9967aa3095eb6b431eb (patch) | |
tree | 5cc3649f5087c8f618e3d9fc27c173cf725f99d3 /src/libs/sqlite | |
parent | f6f11b53a75012c6530a4bda8edd2e66b030121f (diff) | |
download | qt-creator-dfb9e4355f14afd9b543b9967aa3095eb6b431eb.tar.gz |
Sqlite: Transaction catch exception in destructor
Fixes coverity warning. We want to throw an exception in the destructor
in this case, which is save because it is a RAII pattern and holds
only trivial values. Actually this is the only way to communicate that
rollback was failing. It is quite rare that it will be happen without an
exception is already thrown.
There is a non throwing variant too if you want to use it as a class
member.
Change-Id: Ie71ead19678619465c6ad9334d36ee666225dce7
Reviewed-by: Ivan Donchevskii <ivan.donchevskii@qt.io>
Diffstat (limited to 'src/libs/sqlite')
-rw-r--r-- | src/libs/sqlite/sqlitetransaction.h | 77 |
1 files changed, 62 insertions, 15 deletions
diff --git a/src/libs/sqlite/sqlitetransaction.h b/src/libs/sqlite/sqlitetransaction.h index 4fe80d27ec..c58519eb7d 100644 --- a/src/libs/sqlite/sqlitetransaction.h +++ b/src/libs/sqlite/sqlitetransaction.h @@ -27,6 +27,7 @@ #include "sqliteglobal.h" +#include <exception> #include <mutex> namespace Sqlite { @@ -52,12 +53,6 @@ public: class AbstractTransaction { public: - ~AbstractTransaction() - { - if (!m_isAlreadyCommited) - m_interface.rollback(); - } - AbstractTransaction(const AbstractTransaction &) = delete; AbstractTransaction &operator=(const AbstractTransaction &) = delete; @@ -73,39 +68,91 @@ protected: { } -private: +protected: TransactionInterface &m_interface; bool m_isAlreadyCommited = false; }; -class DeferredTransaction final : public AbstractTransaction +class AbstractThrowingTransaction : public AbstractTransaction { public: - DeferredTransaction(TransactionInterface &interface) + ~AbstractThrowingTransaction() noexcept(false) + { + try { + if (!m_isAlreadyCommited) + m_interface.rollback(); + } catch (...) { + if (!std::uncaught_exception()) + throw; + } + } + +protected: + AbstractThrowingTransaction(TransactionInterface &interface) : AbstractTransaction(interface) { - interface.deferredBegin(); } }; -class ImmediateTransaction final : public AbstractTransaction +class AbstractNonThrowingDestructorTransaction : public AbstractTransaction { public: - ImmediateTransaction(TransactionInterface &interface) + ~AbstractNonThrowingDestructorTransaction() + { + try { + if (!m_isAlreadyCommited) + m_interface.rollback(); + } catch (...) { + } + } + +protected: + AbstractNonThrowingDestructorTransaction(TransactionInterface &interface) : AbstractTransaction(interface) { + } +}; + +template <typename BaseTransaction> +class BasicDeferredTransaction final : public BaseTransaction +{ +public: + BasicDeferredTransaction(TransactionInterface &interface) + : BaseTransaction(interface) + { + interface.deferredBegin(); + } +}; + +using DeferredTransaction = BasicDeferredTransaction<AbstractThrowingTransaction>; +using DeferredNonThrowingDestructorTransaction = BasicDeferredTransaction<AbstractNonThrowingDestructorTransaction>; + +template <typename BaseTransaction> +class BasicImmediateTransaction final : public BaseTransaction +{ +public: + BasicImmediateTransaction(TransactionInterface &interface) + : BaseTransaction(interface) + { interface.immediateBegin(); } }; -class ExclusiveTransaction final : public AbstractTransaction +using ImmediateTransaction = BasicImmediateTransaction<AbstractThrowingTransaction>; +using ImmediateNonThrowingDestructorTransaction = BasicImmediateTransaction<AbstractNonThrowingDestructorTransaction>; + +template <typename BaseTransaction> +class BasicExclusiveTransaction final : public BaseTransaction { public: - ExclusiveTransaction(TransactionInterface &interface) - : AbstractTransaction(interface) + BasicExclusiveTransaction(TransactionInterface &interface) + : BaseTransaction(interface) { interface.exclusiveBegin(); } }; +using ExclusiveTransaction = BasicExclusiveTransaction<AbstractThrowingTransaction>; +using ExclusiveNonThrowingDestructorTransaction = BasicExclusiveTransaction<AbstractNonThrowingDestructorTransaction>; + } // namespace Sqlite |