File indexing completed on 2024-12-22 04:17:23

0001 /***************************************************************************
0002  *                                                                         *
0003  *   copyright : (C) 2007 The University of Toronto                        *
0004  *                   netterfield@astro.utoronto.ca                         *
0005  *                                                                         *
0006  *   This program is free software; you can redistribute it and/or modify  *
0007  *   it under the terms of the GNU General Public License as published by  *
0008  *   the Free Software Foundation; either version 2 of the License, or     *
0009  *   (at your option) any later version.                                   *
0010  *                                                                         *
0011  ***************************************************************************/
0012 
0013 #include "updatemanager.h"
0014 
0015 #include "primitive.h"
0016 #include "datasource.h"
0017 #include "objectstore.h"
0018 #include "measuretime.h"
0019 #include <QCoreApplication>
0020 #include <QTimer>
0021 #include <QDebug>
0022 
0023 #define DEFAULT_MIN_UPDATE_PERIOD 2000
0024 
0025 namespace Kst {
0026 
0027 static UpdateManager *_self = 0;
0028 void UpdateManager::cleanup() {
0029   delete _self;
0030   _self = 0;
0031 }
0032 
0033 
0034 UpdateManager *UpdateManager::self() {
0035   if (!_self) {
0036     _self = new UpdateManager;
0037     qAddPostRoutine(cleanup);
0038   }
0039   return _self;
0040 }
0041 
0042 
0043 UpdateManager::UpdateManager() {
0044   _serial = 0;
0045   _minUpdatePeriod = DEFAULT_MIN_UPDATE_PERIOD;
0046   _paused = false;
0047   _store = 0;
0048   _delayedUpdateScheduled = false;
0049   _updateInProgress = false;
0050   _time.start();
0051 }
0052 
0053 
0054 UpdateManager::~UpdateManager() {
0055 }
0056 
0057 void UpdateManager::delayedUpdates() {
0058   _delayedUpdateScheduled = false;
0059   doUpdates();
0060 }
0061 
0062 void UpdateManager::doUpdates(bool forceImmediate) {
0063   if (_delayedUpdateScheduled && !forceImmediate) {
0064     return;
0065   }
0066 
0067   if (!_store) {
0068     return;
0069   }
0070 
0071   //FIXME: should we just skip updating data sources in this case?
0072   if (_paused && !forceImmediate) {
0073     return;
0074   }
0075 
0076   int dT = _time.elapsed();
0077   if (((dT<_minUpdatePeriod) || (_updateInProgress)) && (!forceImmediate)) {
0078     if (!_delayedUpdateScheduled) {
0079       _delayedUpdateScheduled = true;
0080       int deferTime = _minUpdatePeriod-dT;
0081       if (deferTime <= 0) {
0082         deferTime = 20; // if an update is already in progress, wait this long to check again.
0083       }
0084       QTimer::singleShot(deferTime, this, SLOT(delayedUpdates()));
0085     }
0086     return;
0087   }
0088   _updateInProgress = true;
0089   _time.restart();
0090 
0091   _serial++;
0092 
0093   int n_updated=0, n_deferred=0, n_unchanged = 0;
0094   qint64 retval;
0095 
0096   // update the datasources
0097   foreach (DataSourcePtr ds, _store->dataSourceList()) {
0098     ds->writeLock();
0099     retval = ds->objectUpdate(_serial);
0100     ds->unlock();
0101     if (retval == Object::Updated) n_updated++;
0102     else if (retval == Object::Deferred) n_deferred++;
0103     else if (retval == Object::NoChange) n_unchanged++;
0104   }
0105 
0106   //MeasureTime t(" UpdateManager::doUpdates loop");
0107 
0108   int i_loop = retval = 0;
0109   int maxloop = _store->objectList().size();
0110   do {
0111     n_updated = n_unchanged = n_deferred = 0;
0112     // update data objects
0113     foreach (ObjectPtr p, _store->objectList()) {
0114       p->writeLock();
0115       retval = p->objectUpdate(_serial);
0116       p->unlock();
0117 
0118       if (retval == Object::Updated) n_updated++;
0119       else if (retval == Object::Deferred) n_deferred++;
0120       else if (retval == Object::NoChange) n_unchanged++;
0121     }
0122     maxloop = qMin(maxloop,n_deferred);
0123     i_loop++;
0124   } while ((n_deferred + n_updated > 0) && (i_loop<=maxloop));
0125 
0126   if (forceImmediate) {
0127     foreach(DataSourcePtr ds, _store->dataSourceList()) {
0128         ds->vector().readingDone();
0129     }
0130   }
0131 
0132   emit objectsUpdated(_serial);
0133 }
0134 }
0135 
0136 // vim: ts=2 sw=2 et