signon
8.58
|
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