File indexing completed on 2024-11-10 04:40:45
0001 /* 0002 SPDX-FileCopyrightText: 2016 Daniel Vrátil <dvratil@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "akonadicore_debug.h" 0008 #include "session_p.h" 0009 #include "sessionthread_p.h" 0010 0011 #include <QCoreApplication> 0012 #include <QThread> 0013 0014 Q_DECLARE_METATYPE(Akonadi::Connection::ConnectionType) 0015 Q_DECLARE_METATYPE(Akonadi::Connection *) 0016 Q_DECLARE_METATYPE(Akonadi::CommandBuffer *) 0017 0018 using namespace Akonadi; 0019 0020 SessionThread::SessionThread(QObject *parent) 0021 : QObject(parent) 0022 { 0023 qRegisterMetaType<Connection::ConnectionType>(); 0024 qRegisterMetaType<Connection *>(); 0025 qRegisterMetaType<CommandBuffer *>(); 0026 0027 auto thread = new QThread(); 0028 thread->setObjectName(QLatin1StringView("SessionThread")); 0029 moveToThread(thread); 0030 thread->start(); 0031 } 0032 0033 SessionThread::~SessionThread() 0034 { 0035 QMetaObject::invokeMethod(this, &SessionThread::doThreadQuit, Qt::QueuedConnection); 0036 if (!thread()->wait(10 * 1000)) { 0037 thread()->terminate(); 0038 // Make sure to wait until it's done, otherwise it can crash when the pthread callback is called 0039 thread()->wait(); 0040 } 0041 delete thread(); 0042 } 0043 0044 void SessionThread::addConnection(Connection *connection) 0045 { 0046 connection->moveToThread(thread()); 0047 const bool invoke = QMetaObject::invokeMethod(this, "doAddConnection", Qt::BlockingQueuedConnection, Q_ARG(Akonadi::Connection *, connection)); 0048 Q_ASSERT(invoke); 0049 Q_UNUSED(invoke) 0050 } 0051 0052 void SessionThread::doAddConnection(Connection *connection) 0053 { 0054 Q_ASSERT(thread() == QThread::currentThread()); 0055 Q_ASSERT(!mConnections.contains(connection)); 0056 0057 connect(connection, &QObject::destroyed, this, [this](QObject *obj) { 0058 mConnections.removeOne(static_cast<Connection *>(obj)); 0059 }); 0060 mConnections.push_back(connection); 0061 } 0062 0063 void SessionThread::destroyConnection(Connection *connection) 0064 { 0065 if (QCoreApplication::closingDown()) { 0066 return; 0067 } 0068 0069 const bool invoke = QMetaObject::invokeMethod(this, "doDestroyConnection", Qt::BlockingQueuedConnection, Q_ARG(Akonadi::Connection *, connection)); 0070 Q_ASSERT(invoke); 0071 Q_UNUSED(invoke) 0072 } 0073 0074 void SessionThread::doDestroyConnection(Connection *connection) 0075 { 0076 Q_ASSERT(thread() == QThread::currentThread()); 0077 Q_ASSERT(mConnections.contains(connection)); 0078 0079 connection->disconnect(this); 0080 connection->doCloseConnection(); 0081 mConnections.removeAll(connection); 0082 delete connection; 0083 } 0084 0085 void SessionThread::doThreadQuit() 0086 { 0087 Q_ASSERT(thread() == QThread::currentThread()); 0088 0089 for (Connection *conn : std::as_const(mConnections)) { 0090 conn->disconnect(this); 0091 conn->doCloseConnection(); // we can call directly because we are in the correct thread 0092 delete conn; 0093 } 0094 0095 thread()->quit(); 0096 } 0097 0098 #include "moc_sessionthread_p.cpp"