signon  8.58
signondisposable.cpp
Go to the documentation of this file.
00001 /*
00002  * This file is part of signon
00003  *
00004  * Copyright (C) 2010 Nokia Corporation.
00005  *
00006  * Contact: Alberto Mardegan <alberto.mardegan@canonical.com>
00007  *
00008  * This library is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU Lesser General Public License
00010  * version 2.1 as published by the Free Software Foundation.
00011  *
00012  * This library is distributed in the hope that it will be useful, but
00013  * WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
00020  * 02110-1301 USA
00021  */
00022 
00023 #include "signondisposable.h"
00024 
00025 #include <QTimer>
00026 
00027 namespace SignonDaemonNS {
00028 
00029 static QList<SignonDisposable *> disposableObjects;
00030 static QPointer<QTimer> notifyTimer = 0;
00031 static QPointer<QTimer> disposeTimer = 0;
00032 
00033 SignonDisposable::SignonDisposable(int maxInactivity, QObject *parent):
00034     QObject(parent),
00035     maxInactivity(maxInactivity),
00036     autoDestruct(true)
00037 {
00038     disposableObjects.append(this);
00039 
00040     if (disposeTimer != 0) {
00041         int interval = (maxInactivity + 2) * 1000;
00042         if (interval > disposeTimer->interval())
00043             disposeTimer->setInterval(interval);
00044         QObject::connect(disposeTimer, SIGNAL(timeout()),
00045                          this, SLOT(destroyUnused()));
00046     }
00047 
00048     // mark as used
00049     keepInUse();
00050 }
00051 
00052 SignonDisposable::~SignonDisposable()
00053 {
00054     disposableObjects.removeOne(this);
00055 }
00056 
00057 void SignonDisposable::keepInUse() const
00058 {
00059     struct timespec ts;
00060 
00061     if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
00062         qWarning("Couldn't get time from monotonic clock");
00063         return;
00064     }
00065     lastActivity = ts.tv_sec;
00066 
00067     if (notifyTimer != 0) {
00068         notifyTimer->stop();
00069     }
00070     if (disposeTimer != 0) {
00071         disposeTimer->start();
00072     }
00073 }
00074 
00075 void SignonDisposable::setAutoDestruct(bool value) const
00076 {
00077     autoDestruct = value;
00078     keepInUse();
00079 }
00080 
00081 void SignonDisposable::invokeOnIdle(int maxInactivity,
00082                                     QObject *object, const char *member)
00083 {
00084     notifyTimer = new QTimer(object);
00085     notifyTimer->setSingleShot(true);
00086     notifyTimer->setInterval(maxInactivity * 1000);
00087     QObject::connect(notifyTimer, SIGNAL(timeout()),
00088                      object, member);
00089 
00090     /* In addition to the notifyTimer, we create another timer to let
00091      * destroyUnused() to run when we expect that some SignonDisposable object
00092      * might be inactive: that is, a couple of seconds later than the maximum
00093      * inactivity interval. This timer is triggered by the keepInUse() method.
00094      */
00095     disposeTimer = new QTimer(object);
00096     disposeTimer->setSingleShot(true);
00097     int disposableMaxInactivity = 0;
00098     foreach (SignonDisposable *disposable, disposableObjects) {
00099         QObject::connect(disposeTimer, SIGNAL(timeout()),
00100                          disposable, SLOT(destroyUnused()));
00101         if (disposableMaxInactivity < disposable->maxInactivity)
00102             disposableMaxInactivity = disposable->maxInactivity;
00103     }
00104 
00105     // Add a couple of seconds, to run the check after the objects are inactive
00106     disposeTimer->setInterval((disposableMaxInactivity + 2) * 1000);
00107 }
00108 
00109 void SignonDisposable::destroyUnused()
00110 {
00111     struct timespec ts;
00112 
00113     if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
00114         qWarning("Couldn't get time from monotonic clock");
00115         return;
00116     }
00117 
00118     foreach (SignonDisposable *object, disposableObjects) {
00119         if (object->autoDestruct &&
00120             (ts.tv_sec - object->lastActivity > object->maxInactivity)) {
00121             TRACE() << "Object unused, deleting: " << object;
00122             object->destroy();
00123             disposableObjects.removeOne(object);
00124         }
00125     }
00126 
00127     if (disposableObjects.isEmpty() && notifyTimer != 0) {
00128         TRACE() << "No disposable objects, starting notification timer";
00129         notifyTimer->start();
00130     }
00131 }
00132 
00133 } //namespace SignonDaemonNS