ATLAS Offline Software
Loading...
Searching...
No Matches
VP1Prioritiser.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3*/
4
6// //
7// Implementation of class VP1Prioritiser //
8// //
9// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> //
10// //
11// Initial version: April 2007 //
12// //
14
17#include "VP1Base/IVP1System.h"
18#include <QTime>
19#include <QElapsedTimer>
20#include <QQueue>
21#include <QSet>
22#include <map>
23#include <cassert>
24
28
29//____________________________________________________________________
31public:
32
34 public:
40 void addTimeMeasurement(const double&);
41 double refreshtime() const { return m_timing; }
42 private:
43 double m_timing;
44 double m_priority;
45 const bool m_accumulator;
47 void calcPriority();
49 void removeFromPriMap();
50 QQueue<double> m_timemeasurements;
51 };
52
54 //The following map is for prioritising the order of system refreshes:
55 typedef std::multimap<double,IVP1System*> Pri2SysMap;
56 Pri2SysMap priority2sys;//This map is kept updated automatically by the SystemInfo objects.
57
58 QSet<IVP1ChannelWidget*> visiblechannels, soonvisiblechannels;
60
61 QHash<IVP1System*,SystemInfo*> sys2info;
62
63 QElapsedTimer * stopwatch;
65
66 void updateSysinfoWithVisibilityState(const QSet<IVP1ChannelWidget*>& channels,
68
69
70 std::set<IVP1System *>::const_iterator itsys, itsysE;
71};
72
76
77//____________________________________________________________________
79 : system(s), m_priority(117117.117),
80 m_accumulator(cw->isAccumulator()),m_vs(vs),m_d(d)
81{
82 //If another system with the same name exists already, we use that
83 //timing as a reasonable guess. Otherwise we use the average of the
84 //other channels. Failing that we use a default of 500ms.:
85 double tmp(0);
86 bool found(false);
87 QHash<IVP1System*,Imp::SystemInfo*>::iterator itE = m_d->sys2info.end();
88 for (QHash<IVP1System*,Imp::SystemInfo*>::iterator it=m_d->sys2info.begin();it!=itE;++it) {
89 if ( it.key()->name() == s->name() ) {
90 m_timing=it.value()->refreshtime();
91 found=true;
92 break;
93 }
94 tmp += m_timing=it.value()->refreshtime();
95 }
96 if (!found&&!m_d->sys2info.empty())
97 m_timing = tmp/m_d->sys2info.count();
98 else
99 m_timing=500;
100
101 calcPriority();
102}
103
104//____________________________________________________________________
109
110//____________________________________________________________________
112{
113 //Fixme: When do we get tabmanager setVisible signals? At startup? When channels are added?
114 //Fixme: Do not emit these during file loading!!
115 if (m_vs==vs)
116 return;
117 m_vs = vs;
118 calcPriority();
119}
120
121//____________________________________________________________________
123{
124 //Keep the seven latest measurements, and use a truncated mean as
125 //final estimate.
126
127 m_timemeasurements.enqueue(t);
128 if (m_timemeasurements.count()==8)
129 m_timemeasurements.dequeue();
130
131 QList<double> tmplist = m_timemeasurements;
132 std::sort(tmplist.begin(), tmplist.end());
133
134 switch(tmplist.count()) {
135 case 1: m_timing = tmplist.at(0); break;
136 case 2: m_timing = 0.5*(tmplist.at(0)+tmplist.at(1)); break;
137 case 3: m_timing = tmplist.at(1); break;
138 case 4: m_timing = 0.5*(tmplist.at(1)+tmplist.at(2)); break;
139 case 5: m_timing = (tmplist.at(1)+tmplist.at(2)+tmplist.at(3))/3.0; break;
140 case 6: m_timing = 0.5*(tmplist.at(2)+tmplist.at(3)); break;
141 case 7: m_timing = (tmplist.at(2)+tmplist.at(3)+tmplist.at(4))/3.0; break;
142 default: assert(0&&"Should never happen"); break;
143 }
144
145 calcPriority();
146}
147
148//____________________________________________________________________
150{
151 //1) Remove from m_d->priority2sys map
152
153 if (m_priority!=117117.117)
155
156 //2) Calculate new priority
157
158 //Priority is based on how long the systems take to refresh (the
159 //fastest gets refreshed first). In order to ensure that visible,
160 //soonvisible, and accumulators gets priority they get a bonus of
161 //30s, XXXms, and 100ms respectively (where XXX depends on the scenario):
162
163 m_priority = m_timing + (m_vs==VISIBLE?-30000.0:(m_vs==SOONVISIBLE?-m_d->soonvisbonus:0.0)) + (m_accumulator?-100.0:0.0);
164
165 //3) Add to m_d->priority2sys map
166
167 std::pair<double,IVP1System*> a(m_priority,system);
168 m_d->priority2sys.insert(a);
169}
170
171//____________________________________________________________________
173{
174 //Fixme: Cache itp and it (in class Imp even?)!
175 std::pair<Pri2SysMap::iterator, Pri2SysMap::iterator> itp(m_d->priority2sys.equal_range(m_priority));
176 Pri2SysMap::iterator it = itp.first;
177 for (;it!=itp.second;++it) {
178 if (it->second==system) {
179 m_d->priority2sys.erase(it);
180 break;
181 }
182 }
183 assert(it != itp.second);
184}
185
189
190//____________________________________________________________________
192 : QObject(parent), m_d(new Imp)
193{
194 m_d->prioritiser=this;
195 m_d->stopwatch = new QElapsedTimer();
196 m_d->currenttimedsystem=0;
197 m_d->soonvisbonus=0;
198}
199
200//____________________________________________________________________
202{
203 delete m_d->stopwatch;
204 delete m_d; m_d=0;
205}
206
207//___________________________________________________________________
209 Imp::Pri2SysMap::iterator itE = m_d->priority2sys.end();
210 for (Imp::Pri2SysMap::iterator it=m_d->priority2sys.begin();it!=itE;++it) {
211 if ( it->second->state()==IVP1System::ERASED &&it->second->activeState()==IVP1System::ON )
212 return it->second;
213 }
214 return 0;
215}
216
217//___________________________________________________________________
219 QList<IVP1System*> tmp;
220 Imp::Pri2SysMap::iterator itE = m_d->priority2sys.end();
221 for (Imp::Pri2SysMap::iterator it=m_d->priority2sys.begin();it!=itE;++it) {
222 if ( it->second->state()==IVP1System::REFRESHED )
223 tmp << it->second;
224 }
225 return tmp;
226}
227
228
229//___________________________________________________________________
231{
232 double tmp(0);
233 QHash<IVP1System*,Imp::SystemInfo*>::iterator itE = m_d->sys2info.end();
234 for (QHash<IVP1System*,Imp::SystemInfo*>::iterator it=m_d->sys2info.begin();it!=itE;++it) {
235 if ( it.key()->state()==IVP1System::ERASED &&it.key()->activeState()==IVP1System::ON )
236 tmp += it.value()->refreshtime();
237 }
238 return tmp;
239}
240
241//___________________________________________________________________
243{
244 assert(!m_d->currenttimedsystem);
245 m_d->stopwatch->start();
246 m_d->currenttimedsystem=s;
247 assert(m_d->sys2info.contains(s));
248 return m_d->sys2info[s]->refreshtime();
249}
250
251
252//___________________________________________________________________
254{
255 return static_cast<double>(m_d->stopwatch->elapsed());
256}
257
258//___________________________________________________________________
260{
261 assert(m_d->currenttimedsystem);
262 double timing = static_cast<double>(m_d->stopwatch->elapsed());
263 if (m_d->sys2info.contains(m_d->currenttimedsystem)) {//This check, since the corresponding channel might have become uncreated in the meantime.
264 m_d->sys2info[m_d->currenttimedsystem]->addTimeMeasurement(timing);
265 }
266 m_d->currenttimedsystem=0;
267 return timing;
268}
269
270//____________________________________________________________________
272 m_d->itsys = cw->systems().begin();
273 m_d->itsysE = cw->systems().end();
274}
275
276//___________________________________________________________________
277void VP1Prioritiser::Imp::updateSysinfoWithVisibilityState(const QSet<IVP1ChannelWidget*>& channels,
279 for(IVP1ChannelWidget*cw : channels) {
280 for (prioritiser->setupSysItr(cw);itsys!=itsysE;++itsys) {
281 assert(sys2info.contains(*itsys));
282 //if (sys2info.contains(*itsys))//This check since channel deletion might have triggered this update.
283 sys2info[*itsys]->setVisibilityState(vs);
284 }
285 }
286}
287
288//___________________________________________________________________
289void VP1Prioritiser::visibleChannelsChanged(const QSet<IVP1ChannelWidget*>&newvis,
290 const QSet<IVP1ChannelWidget*>&newsoonvis,
291 const double& soonvisbonus)
292{
293 if (m_d->visiblechannels==newvis&&m_d->soonvisiblechannels==newsoonvis&&m_d->soonvisbonus==soonvisbonus)
294 return;
295 m_d->updateSysinfoWithVisibilityState(m_d->visiblechannels,Imp::SystemInfo::NOTVISIBLE);
296 m_d->updateSysinfoWithVisibilityState(m_d->soonvisiblechannels,Imp::SystemInfo::NOTVISIBLE);
297 m_d->updateSysinfoWithVisibilityState(newvis,Imp::SystemInfo::VISIBLE);
298 m_d->updateSysinfoWithVisibilityState(newsoonvis,Imp::SystemInfo::SOONVISIBLE);
299 m_d->visiblechannels = newvis;
300 m_d->soonvisiblechannels = newsoonvis;
301 m_d->soonvisbonus = soonvisbonus;
302}
303
304//___________________________________________________________________
306{
307 bool visible = m_d->visiblechannels.contains(cw);
308 bool soonvisible = m_d->soonvisiblechannels.contains(cw);
309 assert(!(visible&&soonvisible));
310 for (setupSysItr(cw);m_d->itsys!=m_d->itsysE;++m_d->itsys) {
311 assert(!m_d->sys2info.contains(*(m_d->itsys)));
312 Imp::SystemInfo* info = new Imp::SystemInfo(*(m_d->itsys),m_d,cw,
314 m_d->sys2info.insert(*(m_d->itsys),info);
315 }
316}
317
318//___________________________________________________________________
320{
321 for (setupSysItr(cw);m_d->itsys!=m_d->itsysE;++m_d->itsys) {
322 assert(m_d->sys2info.contains(*(m_d->itsys)));
323 delete m_d->sys2info[*(m_d->itsys)];
324 m_d->sys2info.remove(*(m_d->itsys));
325 }
326 if (m_d->visiblechannels.contains(cw))
327 m_d->visiblechannels.remove(cw);
328 if (m_d->soonvisiblechannels.contains(cw))
329 m_d->soonvisiblechannels.remove(cw);
330}
static Double_t a
const std::set< IVP1System * > & systems()
void setVisibilityState(const VisibilityState &)
void addTimeMeasurement(const double &)
SystemInfo(IVP1System *, Imp *, IVP1ChannelWidget *, const VisibilityState &)
std::set< IVP1System * >::const_iterator itsys
void updateSysinfoWithVisibilityState(const QSet< IVP1ChannelWidget * > &channels, const SystemInfo::VisibilityState &vs)
VP1Prioritiser * prioritiser
QElapsedTimer * stopwatch
QSet< IVP1ChannelWidget * > soonvisiblechannels
QSet< IVP1ChannelWidget * > visiblechannels
std::set< IVP1System * >::const_iterator itsysE
QHash< IVP1System *, SystemInfo * > sys2info
IVP1System * currenttimedsystem
std::multimap< double, IVP1System * > Pri2SysMap
virtual ~VP1Prioritiser()
void setupSysItr(IVP1ChannelWidget *cw)
double estimateRemainingCalcTime() const
double elapsedTiming_Refresh()
void visibleChannelsChanged(const QSet< IVP1ChannelWidget * > &vis, const QSet< IVP1ChannelWidget * > &soonvis, const double &soonvisbonus)
IVP1System * nextErasedActiveSystemByPriority()
double endTiming_Refresh()
QList< IVP1System * > getSystemsToEraseByPriority()
VP1Prioritiser(QObject *parent)
void channelCreated(IVP1ChannelWidget *)
double beginTiming_Refresh(IVP1System *)
void channelUncreated(IVP1ChannelWidget *)
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.