File indexing completed on 2024-06-23 05:14:14

0001 /* -*- mode: c++; c-basic-offset:4 -*-
0002     uiserver/sessiondata.cpp
0003 
0004     This file is part of Kleopatra, the KDE keymanager
0005     SPDX-FileCopyrightText: 2009 Klarälvdalens Datakonsult AB
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 
0010 #include <config-kleopatra.h>
0011 
0012 #include "sessiondata.h"
0013 
0014 #include "kleopatra_debug.h"
0015 
0016 #include <QMutex>
0017 
0018 using namespace Kleo;
0019 
0020 static const int GARBAGE_COLLECTION_INTERVAL = 60000; // 1min
0021 
0022 static QMutex mutex;
0023 
0024 SessionData::SessionData()
0025     : mementos()
0026     , ref(0)
0027     , ripe(false)
0028 {
0029 }
0030 
0031 // static
0032 std::shared_ptr<SessionDataHandler> SessionDataHandler::instance()
0033 {
0034     mutex.lock();
0035     static SessionDataHandler handler;
0036     return std::shared_ptr<SessionDataHandler>(&handler, [](SessionDataHandler *) {
0037         mutex.unlock();
0038     });
0039 }
0040 
0041 SessionDataHandler::SessionDataHandler()
0042     : QObject()
0043     , data()
0044     , timer()
0045 {
0046     timer.setInterval(GARBAGE_COLLECTION_INTERVAL);
0047     timer.setSingleShot(false);
0048 }
0049 
0050 void SessionDataHandler::enterSession(unsigned int id)
0051 {
0052     qCDebug(KLEOPATRA_LOG) << id;
0053     const std::shared_ptr<SessionData> sd = sessionDataInternal(id);
0054     Q_ASSERT(sd);
0055     ++sd->ref;
0056     sd->ripe = false;
0057 }
0058 
0059 void SessionDataHandler::exitSession(unsigned int id)
0060 {
0061     qCDebug(KLEOPATRA_LOG) << id;
0062     const std::shared_ptr<SessionData> sd = sessionDataInternal(id);
0063     Q_ASSERT(sd);
0064     if (--sd->ref <= 0) {
0065         sd->ref = 0;
0066         sd->ripe = false;
0067         if (!timer.isActive()) {
0068             QMetaObject::invokeMethod(&timer, "start", Qt::QueuedConnection);
0069         }
0070     }
0071 }
0072 
0073 std::shared_ptr<SessionData> SessionDataHandler::sessionDataInternal(unsigned int id) const
0074 {
0075     auto it = data.lower_bound(id);
0076     if (it == data.end() || it->first != id) {
0077         const std::shared_ptr<SessionData> sd(new SessionData);
0078         it = data.insert(it, std::make_pair(id, sd));
0079     }
0080     return it->second;
0081 }
0082 
0083 std::shared_ptr<SessionData> SessionDataHandler::sessionData(unsigned int id) const
0084 {
0085     return sessionDataInternal(id);
0086 }
0087 
0088 void SessionDataHandler::clear()
0089 {
0090     data.clear();
0091 }
0092 
0093 void SessionDataHandler::slotCollectGarbage()
0094 {
0095     const QMutexLocker locker(&mutex);
0096     unsigned int alive = 0;
0097     auto it = data.begin(), end = data.end();
0098     while (it != end)
0099         if (it->second->ripe) {
0100             data.erase(it++);
0101         } else if (!it->second->ref) {
0102             it->second->ripe = true;
0103             ++it;
0104         } else {
0105             ++alive;
0106             ++it;
0107         }
0108     if (alive == data.size()) {
0109         QMetaObject::invokeMethod(&timer, "stop", Qt::QueuedConnection);
0110     }
0111 }
0112 
0113 #include "moc_sessiondata.cpp"