signon  8.42
signondisposable.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of signon
3  *
4  * Copyright (C) 2010 Nokia Corporation.
5  *
6  * Contact: Alberto Mardegan <alberto.mardegan@canonical.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * version 2.1 as published by the Free Software Foundation.
11  *
12  * This library is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20  * 02110-1301 USA
21  */
22 
23 #include "signondisposable.h"
24 
25 #include <QTimer>
26 
27 namespace SignonDaemonNS {
28 
29 static QList<SignonDisposable *> disposableObjects;
30 static QPointer<QTimer> notifyTimer = 0;
31 static QPointer<QTimer> disposeTimer = 0;
32 
33 SignonDisposable::SignonDisposable(int maxInactivity, QObject *parent):
34  QObject(parent),
35  maxInactivity(maxInactivity),
36  autoDestruct(true)
37 {
38  disposableObjects.append(this);
39 
40  if (disposeTimer != 0) {
41  int interval = (maxInactivity + 2) * 1000;
42  if (interval > disposeTimer->interval())
43  disposeTimer->setInterval(interval);
44  QObject::connect(disposeTimer, SIGNAL(timeout()),
45  this, SLOT(destroyUnused()));
46  }
47 
48  // mark as used
49  keepInUse();
50 }
51 
53 {
54  disposableObjects.removeOne(this);
55 }
56 
58 {
59  struct timespec ts;
60 
61  if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
62  qWarning("Couldn't get time from monotonic clock");
63  return;
64  }
65  lastActivity = ts.tv_sec;
66 
67  if (notifyTimer != 0) {
68  notifyTimer->stop();
69  }
70  if (disposeTimer != 0) {
71  disposeTimer->start();
72  }
73 }
74 
75 void SignonDisposable::setAutoDestruct(bool value) const
76 {
77  autoDestruct = value;
78  keepInUse();
79 }
80 
81 void SignonDisposable::invokeOnIdle(int maxInactivity,
82  QObject *object, const char *member)
83 {
84  notifyTimer = new QTimer(object);
85  notifyTimer->setSingleShot(true);
86  notifyTimer->setInterval(maxInactivity * 1000);
87  QObject::connect(notifyTimer, SIGNAL(timeout()),
88  object, member);
89 
90  /* In addition to the notifyTimer, we create another timer to let
91  * destroyUnused() to run when we expect that some SignonDisposable object
92  * might be inactive: that is, a couple of seconds later than the maximum
93  * inactivity interval. This timer is triggered by the keepInUse() method.
94  */
95  disposeTimer = new QTimer(object);
96  disposeTimer->setSingleShot(true);
97  int disposableMaxInactivity = 0;
98  foreach (SignonDisposable *disposable, disposableObjects) {
99  QObject::connect(disposeTimer, SIGNAL(timeout()),
100  disposable, SLOT(destroyUnused()));
101  if (disposableMaxInactivity < disposable->maxInactivity)
102  disposableMaxInactivity = disposable->maxInactivity;
103  }
104 
105  // Add a couple of seconds, to run the check after the objects are inactive
106  disposeTimer->setInterval((disposableMaxInactivity + 2) * 1000);
107 }
108 
110 {
111  struct timespec ts;
112 
113  if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
114  qWarning("Couldn't get time from monotonic clock");
115  return;
116  }
117 
118  foreach (SignonDisposable *object, disposableObjects) {
119  if (object->autoDestruct &&
120  (ts.tv_sec - object->lastActivity > object->maxInactivity)) {
121  TRACE() << "Object unused, deleting: " << object;
122  object->destroy();
123  disposableObjects.removeOne(object);
124  }
125  }
126 
127  if (disposableObjects.isEmpty() && notifyTimer != 0) {
128  TRACE() << "No disposable objects, starting notification timer";
129  notifyTimer->start();
130  }
131 }
132 
133 } //namespace SignonDaemonNS