File indexing completed on 2024-06-16 04:50:12

0001 /*
0002     SPDX-FileCopyrightText: 2018 Daniel Vrátil <dvratil@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #pragma once
0008 
0009 class QObject;
0010 
0011 #include <QMutex>
0012 #include <QQueue>
0013 
0014 #include "private/protocol_p.h"
0015 
0016 #include "akonadicore_debug.h"
0017 
0018 namespace Akonadi
0019 {
0020 class CommandBufferLocker;
0021 class CommandBufferNotifyBlocker;
0022 
0023 class CommandBuffer
0024 {
0025     friend class CommandBufferLocker;
0026     friend class CommandBufferNotifyBlocker;
0027 
0028 public:
0029     struct Command {
0030         qint64 tag;
0031         Protocol::CommandPtr command;
0032     };
0033 
0034     CommandBuffer(QObject *parent, const char *notifySlot)
0035         : mParent(parent)
0036         , mNotifySlot(notifySlot)
0037     {
0038     }
0039 
0040     void enqueue(qint64 tag, const Protocol::CommandPtr &command)
0041     {
0042         mCommands.enqueue({tag, command});
0043         if (mNotify) {
0044             const bool ok = QMetaObject::invokeMethod(mParent, mNotifySlot.constData(), Qt::QueuedConnection);
0045             Q_ASSERT(ok);
0046             Q_UNUSED(ok)
0047         }
0048     }
0049 
0050     inline Command dequeue()
0051     {
0052         return mCommands.dequeue();
0053     }
0054 
0055     inline bool isEmpty() const
0056     {
0057         return mCommands.isEmpty();
0058     }
0059 
0060     inline int size() const
0061     {
0062         return mCommands.size();
0063     }
0064 
0065 private:
0066     Q_DISABLE_COPY_MOVE(CommandBuffer)
0067 
0068     QObject *mParent = nullptr;
0069     QByteArray mNotifySlot;
0070 
0071     QQueue<Command> mCommands;
0072     QMutex mLock;
0073 
0074     bool mNotify = true;
0075 };
0076 
0077 class CommandBufferLocker
0078 {
0079 public:
0080     explicit CommandBufferLocker(CommandBuffer *buffer)
0081         : mBuffer(buffer)
0082     {
0083         relock();
0084     }
0085 
0086     ~CommandBufferLocker()
0087     {
0088         unlock();
0089     }
0090 
0091     inline void unlock()
0092     {
0093         if (mLocked) {
0094             mBuffer->mLock.unlock();
0095             mLocked = false;
0096         }
0097     }
0098 
0099     inline void relock()
0100     {
0101         if (!mLocked) {
0102             mBuffer->mLock.lock();
0103             mLocked = true;
0104         }
0105     }
0106 
0107 private:
0108     Q_DISABLE_COPY_MOVE(CommandBufferLocker)
0109 
0110     CommandBuffer *mBuffer = nullptr;
0111     bool mLocked = false;
0112 };
0113 
0114 class CommandBufferNotifyBlocker
0115 {
0116 public:
0117     explicit CommandBufferNotifyBlocker(CommandBuffer *buffer)
0118         : mBuffer(buffer)
0119     {
0120         mBuffer->mNotify = false;
0121     }
0122 
0123     ~CommandBufferNotifyBlocker()
0124     {
0125         unblock();
0126     }
0127 
0128     void unblock()
0129     {
0130         mBuffer->mNotify = true;
0131     }
0132 
0133 private:
0134     Q_DISABLE_COPY_MOVE(CommandBufferNotifyBlocker)
0135 
0136     CommandBuffer *mBuffer;
0137 };
0138 
0139 } // namespace