File indexing completed on 2025-01-05 04:55:53
0001 /* 0002 utils/uniquelock.cpp 0003 QMutex-compatible replacement for std::unique_lock 0004 0005 This file is part of libkleopatra, the KDE keymanagement library 0006 SPDX-FileCopyrightText: 2008-2021 Free Software Foundation, Inc. 0007 SPDX-FileCopyrightText: 2021 g10 Code GmbH 0008 SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de> 0009 0010 SPDX-License-Identifier: GPL-3.0-or-later WITH GCC-exception-3.1 0011 */ 0012 0013 #include <config-libkleo.h> 0014 0015 #include "uniquelock.h" 0016 0017 #include <libkleo_debug.h> 0018 0019 namespace Kleo 0020 { 0021 0022 UniqueLock::UniqueLock() noexcept 0023 : mMutex{nullptr} 0024 , mOwnsMutex{false} 0025 { 0026 } 0027 0028 UniqueLock::UniqueLock(QMutex &mutex) 0029 : mMutex{std::addressof(mutex)} 0030 , mOwnsMutex{false} 0031 { 0032 lock(); 0033 mOwnsMutex = true; 0034 } 0035 0036 UniqueLock::UniqueLock(QMutex &mutex, DeferLockType) noexcept 0037 : mMutex{std::addressof(mutex)} 0038 , mOwnsMutex{false} 0039 { 0040 } 0041 0042 UniqueLock::UniqueLock(QMutex &mutex, TryToLockType) 0043 : mMutex{std::addressof(mutex)} 0044 , mOwnsMutex{mMutex->try_lock()} 0045 { 0046 } 0047 0048 UniqueLock::UniqueLock(QMutex &mutex, AdoptLockType) noexcept 0049 : mMutex{std::addressof(mutex)} 0050 , mOwnsMutex{true} 0051 { 0052 // XXX calling thread owns mutex 0053 } 0054 0055 UniqueLock::~UniqueLock() 0056 { 0057 if (mOwnsMutex) { 0058 unlock(); 0059 } 0060 } 0061 0062 UniqueLock::UniqueLock(UniqueLock &&u) noexcept 0063 : mMutex{u.mMutex} 0064 , mOwnsMutex{u.mOwnsMutex} 0065 { 0066 u.mMutex = nullptr; 0067 u.mOwnsMutex = false; 0068 } 0069 0070 UniqueLock &UniqueLock::operator=(UniqueLock &&u) noexcept 0071 { 0072 if (mOwnsMutex) { 0073 unlock(); 0074 } 0075 0076 UniqueLock(std::move(u)).swap(*this); 0077 0078 u.mMutex = nullptr; 0079 u.mOwnsMutex = false; 0080 0081 return *this; 0082 } 0083 0084 void UniqueLock::lock() 0085 { 0086 Q_ASSERT(mMutex); 0087 Q_ASSERT(!mOwnsMutex); 0088 if (!mMutex) { 0089 qCWarning(LIBKLEO_LOG) << __func__ << "Error: operation not permitted"; 0090 } else if (mOwnsMutex) { 0091 qCWarning(LIBKLEO_LOG) << __func__ << "Error: resource deadlock would occur"; 0092 } else { 0093 mMutex->lock(); 0094 mOwnsMutex = true; 0095 } 0096 } 0097 0098 bool UniqueLock::try_lock() 0099 { 0100 Q_ASSERT(mMutex); 0101 Q_ASSERT(!mOwnsMutex); 0102 if (!mMutex) { 0103 qCWarning(LIBKLEO_LOG) << __func__ << "Error: operation not permitted"; 0104 return false; 0105 } else if (mOwnsMutex) { 0106 qCWarning(LIBKLEO_LOG) << __func__ << "Error: resource deadlock would occur"; 0107 return false; 0108 } else { 0109 mOwnsMutex = mMutex->try_lock(); 0110 return mOwnsMutex; 0111 } 0112 } 0113 0114 void UniqueLock::unlock() 0115 { 0116 if (!mOwnsMutex) { 0117 qCWarning(LIBKLEO_LOG) << __func__ << "Error: operation not permitted"; 0118 } else if (mMutex) { 0119 mMutex->unlock(); 0120 mOwnsMutex = false; 0121 } 0122 } 0123 0124 void UniqueLock::swap(UniqueLock &u) noexcept 0125 { 0126 std::swap(mMutex, u.mMutex); 0127 std::swap(mOwnsMutex, u.mOwnsMutex); 0128 } 0129 0130 QMutex *UniqueLock::release() noexcept 0131 { 0132 QMutex *ret = mMutex; 0133 mMutex = nullptr; 0134 mOwnsMutex = false; 0135 return ret; 0136 } 0137 0138 bool UniqueLock::owns_lock() const noexcept 0139 { 0140 return mOwnsMutex; 0141 } 0142 0143 UniqueLock::operator bool() const noexcept 0144 { 0145 return owns_lock(); 0146 } 0147 0148 QMutex *UniqueLock::mutex() const noexcept 0149 { 0150 return mMutex; 0151 } 0152 0153 } // namespace Kleo