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