Re: Lahman, how ya doing?
Gregory L. Hansen wrote:
....snip...
including a
chart recorder that saves as a data point an average and standard
deviation over a given time. That's what DoubleTimer is for, because
there will be a sampling time and an averaging time, similarly to the
apparatus. But it reflects what I want "real" to be. There'll be
separate timers for the analog peices, the digital controllers, the chart
recorders, and the switch that turns the beam on and off-- four total,
each with one or more tasks, or control blocks, to manage. All on one
clock.
As another approach, you might have the tasks schedule themselves,
rather than deal with a master-scheduler, queues, events, and timers.
To schedule itself, a task just needs to delay its own execution until
its schedulingInterval has elapsed, then doTheRightThing, and loop.
For example, the following depicts a generic "chart recorder"...
-----
ChartRecorder>>
iVars := samples samplingProcess AveragingProcess
ChartRecorder>>sample: sBlock every: sTime avg: avgBlock every: avgTime
| samplingDelay averagingDelay |
self stopRecording.
samplingInterval := Delay for: sTime.
averagingInterval := Delay for: avgTime.
samplingProcess :=
[ | singleton |
samplingInterval wait.
self samples add: #skip -> #pre.
singleton := self samples.
singleton add: #valid -> sBlock value.
singleton add: #skip -> #post
] fork.
averagingProcess :=
[ | capturedSamples |
averagingInterval wait.
capturedSamples := self captureSamples.
avgBlock value: capturedSamples
] fork.
ChartRecorder>>samples
^samples
ChartRecorder>>captureSamples
| snagged noLongerBeingAddedInto theValidPairs justTheSamples |
snagged := self samples.
samples := OrderedCollection new.
[ snagged isEmpty
or: [snagged last value == #post]
] whileFalse: [Process yield].
noLongerBeingAddedInto := snagged.
theValidPairs :=
noLongerBeingAddedInto select: [:each| each key == #valid].
justTheSamples := theValidPairs collect: [:each| each value].
^justTheSamples
ChartRecorder>>stopRecording
averagingProcess terminate.
samplingProcess terminate.
samples := nil
-----
The other tasks appear similar this one.
Each of them either "knows" its own scheduling interval(s),
or can be told the interval(s) whenever it is being started.
Assuming your OS provides some kind of multitasking,
it should already do what you want done - and if so,
you can just use that. If not, you might still want
to consider building a "Delay" unit, rather than a "Timer".
There doesn't appear to be any value-add (in your context)
to building a custom master/queue/event handling dispatcher.
Regards,
-cstb
.