DML_timer Class
Declared:
#include <DML_timer.h>
Derived From:
[none]
Description
The DML_timer class is a convenience class to make working with QNX timers
easier. Using this class, the programmer is able to create a timer, set up its
timing information, attach a proxy to the process, and start the timer up, all
in one fell swoop. It also provides facilities for starting and stopping the
timers, as well as checking to see if the process loop is too slow to keep up
with the desired timer frequencies.
One function, timer.wait()
, is not used anywhere, because I created
it late in the game. It provides a more clear syntax than Receive(timer,0,0)
,
but does exactly the same thing. This class falls under the 'Quick-n-Dirty'
designation, and a more complete implementation would be interesting to do...
maybe I'll do it sometime when I'm bored. It shouldn't be too difficult.
Public Class Members
Public member data:
timer_t id
pid_t proxy
pid_t proxyTarget
int proxyPriority
Public member functions:
DML_timer()
DML_timer( const DML_timer & )
DML_timer( int, pid_t = SELF )
DML_timer( int, char, pid_t = SELF )
~DML_timer
setPeriod( int )
arm()
stop()
wait()
restart()
timeLeft( struct itmerspec & )
int checkProxyBackup()
clearProxyQueue()
operator pid_t()
See Also:
the WATCOM QNX Timer section
Class Member Functions
DML_timer Constructors
Synopsis:
#include <DML_timer.h>
DML_timer()
DML_timer( DML_timer & )
DML_timer( int, pid_t = SELF )
DML_timer( int, char, pid_t = SELF )
Semantics:
There are four forms of the DML_timer constructors. The first creates a blank
timer which is not armed, nor does it have a period cycle. The second copies
the information stored in another DML_timer class, WITHOUT creating a new timer.
The third creates a timer, which begins running immediately, with the period
(in milliseconds) as the first argument and the target process to be 'pinged'
as the second (which defaults to the calling process). The fourth is like the
third, but creates a one-shot timer when the second argument passed is ONE_SHOT:
otherwise it behaves exactly like the first.
These timers inform a process of timer expiration by triggering a proxy which
is attached to the target process. The constructors, therefore, must create
both a timer and a proxy.
Code Dissection:
This constructor is particularly simple. It stores some data associated with
the timer, the proxy, the target process, and the timing frequency. This information
is all explained well in the QNX Timers section of the WATCOM manual.
Results:
A timer is created, and a proxy is attached, if version 3 or 4 is called. Otherwise,
some data is initialized.
See Also:
~DML_timer
DML_timer Destructor
Synopsis:
#include <DML_timer.h>
DML_timer::~DML_timer
Semantics:
This is the destructor for the timer. It destroys the QNX timer, ditches some
data, , and cleans up. The one thing which it doesn't do is detach the
proxy: it should probably do this, just for cleanliness' sake.
Code Dissection:
Self-explanatory
Results:
Destroys the data structure.
See Also:
DML_timer::DML_timer
DML_timer::setPeriod
Synopsis:
#include <DML_timer.h>
DML_timer::setPeriod( int )
Semantics:
This function sets or changes the period of the timer to the argument, in milliseconds.
Code Dissection:
This function is just a cover for the QNX timer function timer_settime.
Results:
This function changes the period associated with the timer, whether or not the
timer is active or even created.
See Also:
timer_settime
DML_timer::checkProxyBackup()
Synopsis:
#include <DML_timer.h>
int DML_timer::checkProxyBackup()
Semantics:
I stumbled across this while actually looking to solve a different problem,
and promptly incorporated it into the timer class. The function qnx_psinfo
returns information about a process pid: if that process pid happens to belong
to a proxy, some of the data in the _psinfo
struct shows the number
of times the proxy has been triggered minus the number of times it's been Received
from. This function can be used by the programmer to see if the loop being run
is too long for the specified timing rate. Since the proxy gets kicked every
time the real-time timer fires off, if the loop takes too long to execute, it
won't Receive often enough on the proxy. A backlog of proxies builds up, and
the process is no longer running at a controlled rate, since there's always
an available proxy ready to be Received. This function will return values larger
than 1 if this is the case. A call to this function involves the copying of
a significant amount of data (the _psinfo
struct is quite large),
so my recommendation would be to call it every 5th time through the loop, or
thereabouts. If the number returned ever rises above about 5 or 10, then you've
got a serious loop duration problem and should break out of the loop and terminate.
Small numbers (about 3 or 4) consistently recorded means that the loop is right
on the hairy edge of being too long, and the call to checkProxyBackup()
might even be a bad idea, since it is fairly slow.
Code Dissection:
The code just involves a simple call to the qnx_psinfo()
function.
See that function's help file for details.
Results:
Process data is copied, and the number returned indicates the number of proxy
triggers which are waiting to be received. A normal number would be 0, 1, or maybe
2. Numbers between 3 and about 7 mean that some backup is occurring sporadically,
and numbers over 10 mean that serious backup is occurring, and the timer loop
is too long for the frequency chosen.
See Also:
DML_timer::clearProxyQueue
DML_timer::arm
Synopsis:
#include <DML_timer.h>
DML_timer::arm()
Semantics:
This function takes care of actually starting the timer. Essentially, it's the
same as DML_timer::restart.
Code Dissection:
This function detaches the current proxy and destroys the timer, if they exist.
It then creates a proxy, attached to the target process, and arms the timer, using
the proxy id as the timer timeout event. Upon timeout, the timer will trigger
the proxy. See the timer_create function.
Results:
The timer is armed and begins ticking. It will fire off a proxy to the target
process when it expires.
See Also:
timer_create, DML_timer::restart
DML_timer::stop
Synopsis:
#include <DML_timer.h>
DML_timer::stop()
Semantics:
This function stops the DML_timer object from ticking.
Code Dissection:
Sneakily, all this function does is sets the timeout period of the timer to zero...
this has the effect of having an infinite timeout period (don't ask why... see
the timer_settime function if interested)
Results:
The timer stops ticking.
See Also:
DML_timer::restart , timer_settime
DML_timer::restart
Synopsis:
#include <DML_timer.h>
DML_timer::restart
Semantics:
This function restarts a stopped timer. If used on a timer that isn't stopped,
it might result in one missed tick, or more likely one tick which is longer than
specified, so use this function only when you're sure the timer is stopped, or
you'll have to tolerate one inaccurate tick.
Code Dissection:
This function just resets the timing to the proper values, again using timer_settime
Results:
The timer begins ticking again, according to its original state.
See Also:
DML_timer::stop, timer_settime
DML_timer::wait
Synopsis:
#include <DML_timer.h>
DML_timer::wait()
Semantics:
This function is a simple cover for the Receive function. It just blocks until
the timer fires off its proxy.
Code Dissection:
The Receive call waits on the proxy... so the proxy had better be attached to
the calling process! If the timer is attached to a different process, the call
to DML_timer::wait() will hang.
Results:
The process blocks.
See Also:
Receive
DML_timer::timeLeft
Synopsis:
#include <DML_timer.h>
DML_timer::timeLeft( struct itimerspec & )
Semantics:
This function is a cover for timer_gettime: it will put the timing information
into the argument passed in, but the programmer must know how to use it. See the
help file for timer_gettime.
Code Dissection:
Just a simple cover function.
Results:
The timing information relating to the timer object is placed in the argument.
See Also:
timer_gettime
DML_timer::clearProxyQueue
Synopsis:
#include <DML_timer.h>
DML_timer::clearProxyQueue()
Semantics:
This function destroys and re-makes the proxy attached to the target, thereby
clearing the queued proxies which are waiting to be delivered. The primary use
of this function is to clear a backlogged queue which occurred due to an unexpected
processor load.
Code Dissection:
The code simply destroys and reattaches the proxy.
Results:
The queue of proxies waiting to be serviced by the target is eliminated.
See Also:
qnx_proxy_detach, qnx_proxy_attach
DML_timer::operator pid_t
Synopsis:
#include <DML_timer.h>
DML_timer operator pid_t()
Semantics:
This gets at the proxy pid, not the timer id. Used for doing a Receive-block.
Code Dissection:
Just returns a copy of the proxy pid.
Results:
Returns the proxy pid.
See Also:
none