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