[Panel-devel] dataengines and timing revisited

Aaron J. Seigo aseigo at kde.org
Thu Aug 30 04:40:58 CEST 2007


hi =)

a few weeks ago Michael Olbrich posted a patch to allow applets (or whatever) 
to determine when they should be notified of an update. there were a few 
things neither of us was really happy about the patch, but it was a good run 
at it.

today i sat down and drew some pictures and wrote some words using ink on 
paper. totally old school. made me remember (a) why we have computers (my 
hand writing is horrid) and (b) what computers still suck at (sketching 
notes[1]).

here's what i came up powered by the old school love of pen 'n paper:

we can divide the problem into three parts:

Engine updating (U) its data
	U(1) it knows when to update its data, don't try and tell it otherwise
	U(2) engine updates on demand and should avoid updating otherwise

Engine data collection (C) methods
	C(1) synchronous
	C(2) asynchronous

Applet access (A) to data
	A(1) wants data whenever it arrives/changes (rely on the engine)
	A(2) wants data updated periodically (every N ms kick the engine)

and all combinations of U, C and A are valid. meh. this is why i hadn't yet 
either simply whipped up a modification of Michael's patch or something new 
off the cuff and committed it already =)

this can pretty easily lead to insanities where expensive updates are done 
multiple times in a row or a request is triggered by an applet's update 
frequency but the data won't arrive until some unknown time in the future. 

so i'm proposing the following API in DataEngine:

public:
setMinimumUpdateFrequency(int) and int minimumUpdateFrequency() const
	sets the minimumt time in ms between updates.
		< 0 == never update on demand; just let the engine handle it
		0 == update immediately on (every) demand
		>0 == the number of ms that must pass before updates
	i'm still not sure on the default. maybe 500ms?
	an rss feed engine may want to have it at 60000 or even higher
	a cpu temp engine might want it to 0ms or perhaps 20ms
	a hotplug engine probably wants it at -1

protected:
setUpdateFrequency(int) and int updateFrequency() const
	provides a built in timer for the engine (using timerEvent()) and cooperates
	with minUpdateFrequency(), so if an applet kicks an update for a source this
	won't cause a second update to that source

virtual bool updateSource(const QString& source)
	called when a source should be updated. 
	the default implementation is {return true; }
	false is returned when an update is started but async, meaning that emitting
	the proxy QObject's updated signal should occur later in time with the next
	Applet::updated() signal when setData() is called; this implies keeping a
	list of objects needing to emit around. it also implies that updates only 	
	happen when the data arrives; if there are assumptions otherwise in applets,
	they are broken imho.

timerEvent()
	goes through each source and calls updateSource; time out is updateFrequency
	goes through each source, checks the update freq and if they need it,
	pumps the engine fo an update of the data.
	this may cause the Applet::updated() signal to be emitted.

connectSource and connectAllsources now take an optional update frequency, 
much as in Michael's patch

the code then works something like this:

connectSource will connect the applet to the DataContainer's updated() signal 
if the updateFrequency < 1. otherwise we round updateFrequency to a sane 
number and create a QObject that stands in and emits the signal every 
qMin(updateFrequency, minimumUpdateFrequency()). much as in Michael's patch, 
these objects will be shared between objects with the same requested 
frequency period. there won't be a manager for them, however; that will all 
go into DataContainer itself at this point, i think. if this becomes a 
generally useful pattern, we can abstract it out into its own class.

care needs to be taken to ensure that:
   - the DataContainer::updated() signal is emitted when data changes; this 
keeps DataContainer generally useful and obvious in use for the simple case
   - DataContainers are auto-removed appropriately
   - async updates are indeed propogated properly

when a update request gets fired from a DataContainer, the engine will decide 
whether or not to update based on the last updated time. this implies adding 
a timestamp to each DataContainer. this should hopefully prevent a lot of 
expensive re-updating.


this is obviously more complicated than what is there right now but i think it 
is a bit more straight forward than Michael's original patch, introduces 
fewer classes and doesn't introduce regressions in behaviour AFAICS. if there 
are no objections to this approach, i will be finishing this up and 
committing it tomorrow.


remaining caveats: the clock has an interesting problem where it really wants 
to pin the ticks to clock ticks, especially for the minutes-only ... i have 
yet to figure out how to arrange that. without it, it is possible for the 
ticks to drift dramatically so that the time is up 59s out. maybe it's just 
me, but that would suck =) if someone provides a clock that just shows the 
hour, that could be even worse. then again, perhaps the clock, as a special 
case, just continues to manage its own update ticks.

other cool things that could be added: sharing ticks between engines. feels 
like a premature optimization at this point, though it might be nice for 
power consumption ... in any case, we'll see.

[1] it occurs to me that a -really- good note sketcher + inexpensive pen 
device would be a terrific app. i've seem some note takers and they all suck.
[2] nearest 50ms? that gives up to 20 updates a second. should be enough?

-- 
Aaron J. Seigo
humru othro a kohnu se
GPG Fingerprint: 8B8B 2209 0C6F 7C47 B1EA  EE75 D6B7 2EB1 A7F1 DB43

KDE core developer sponsored by Trolltech
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
Url : http://mail.kde.org/pipermail/panel-devel/attachments/20070829/aff7427e/attachment-0001.pgp 


More information about the Panel-devel mailing list