Coin  4.0.10
Coin3D core library
Loading...
Searching...
No Matches
SoSensorManager Class Reference

The SoSensorManager class handles the sensor queues. More...

#include <Inventor/sensors/SoSensorManager.h>

Public Member Functions

 SoSensorManager (void)
 
 ~SoSensorManager ()
 
int doSelect (int nfds, void *readfds, void *writefds, void *exceptfds, struct timeval *userTimeOut)
 
const SbTime & getDelaySensorTimeout (void)
 
void insertDelaySensor (SoDelayQueueSensor *s)
 
void insertTimerSensor (SoTimerQueueSensor *s)
 
SbBool isDelaySensorPending (void)
 
SbBool isTimerSensorPending (SbTime &tm)
 
void processDelayQueue (SbBool isidle)
 
void processImmediateQueue (void)
 
void processTimerQueue (void)
 
void removeDelaySensor (SoDelayQueueSensor *s)
 
void removeRescheduledTimer (SoTimerQueueSensor *s)
 
void removeTimerSensor (SoTimerQueueSensor *s)
 
void rescheduleTimer (SoTimerSensor *s)
 
void setChangedCallback (void(*sensorQueueChangedCB)(void *), void *data)
 
void setDelaySensorTimeout (const SbTime &t)
 

Detailed Description

The SoSensorManager class handles the sensor queues.

There are two major sensor types in Coin, "delay" sensors and "timer" sensors:

  • Delay sensors trigger when the application is otherwise idle. In addition, to avoid starvation in applications that are continually busy, the delay sensor queue also has a timeout which, when reached, will empty the queue anyhow.
  • Timer sensors are set up to trigger at specific, absolute times.

Each of these two types has its own queue, which is handled by the SoSensorManager. The queues are kept in sorted order by SoSensorManager, either according to trigger time (for timer sensors) or by priority (for delay sensors).

The SoSensorManager provides methods for managing these queues, by insertion and removal of sensors, and processing (emptying) of the queues.

The sensor mechanism is crucial in Coin for a number of important features, most notably automatic scheduling redraw upon changes, and for making it possible to set up animations in the scene graph which does not need any additional book-keeping from the application code.

SoSensorManager should usually be considered as an internal class in the Coin API. It is only interesting for application programmers when implementing new window system specific libraries (like Kongsberg Oil & Gas Technologies SoQt, SoXt, SoGtk, SoWin or Sc21) or wrappers. Then one has to set up code to empty the queues at the correct intervals. For detailed information on how to do that, we would advise you to look at the implementation of said mechanisms in the So*-libraries which SIM provides.

Integrating sensors with an event loop

Coin does not run an event loop or perform I/O while the application is blocked. GUI bindings normally integrate the queues with their toolkit's event loop. Applications implementing their own loop can obtain the manager through SoDB::getSensorManager(). The obsolete doSelect() methods do not provide this integration.

Before waiting for I/O or window events, process due timers with processTimerQueue() and immediate sensors with processImmediateQueue(). When the application has no other work ready, processDelayQueue(TRUE) also processes idle sensors. Pass FALSE when processing delay sensors during a busy period; this skips SoIdleSensor instances. The configured delay timeout is implemented by a timer sensor and therefore requires the application to keep processing the timer queue, even while I/O is continuously ready. A zero delay timeout disables this fallback.

isTimerSensorPending() returns an absolute deadline in the time base of SbTime::getTimeOfDay(). Convert it to a relative wait and clamp overdue deadlines to zero:

{
if (!manager->isTimerSensorPending(deadline)) return FALSE;
if (wait < SbTime::zero()) wait = SbTime::zero();
return TRUE;
}
The SbList class is a template container class for lists.
Definition SbList.h:74
The SbTime class instances represents time values.
Definition SbTime.h:50
static SbTime getTimeOfDay(void)
Definition SbTime.cpp:148
static SbTime zero(void)
Definition SbTime.cpp:173
The SoSensorManager class handles the sensor queues.
Definition SoSensorManager.h:43

If this returns TRUE, use the smaller of this wait and the application's own timeout when waiting for events. If it returns FALSE, there is no timer-imposed limit; the application may still have other pending work. Recompute the deadline after dispatching events and processing sensors. A pending delay sensor alone does not require repeated zero-duration waits: an idle-only sensor can remain pending throughout a busy period.

setChangedCallback() can reprogram the event loop's timer or request a wakeup when a queue changes. It is a synchronous callback, with a single registration slot. Notifications are suppressed while sensor queues are being processed, and insertion of an immediate sensor does not notify it. Query the queues when installing the integration and after each dispatch/processing pass; the callback alone is not a complete record of pending work. Prefer deferring queue processing to the event loop rather than running user sensor callbacks inside this notification.

Waiting for descriptor readiness must also allow the next sensor deadline to wake the loop. After readiness, keep the actual I/O and event handlers bounded, for example by using nonblocking I/O. A blocking read or other long operation in the loop delays sensor callbacks and rendering. Another option is to perform blocking I/O in a worker and deliver its results to the thread running the event loop. Scene updates and rendering still need the application's normal dispatch mechanism; processing sensor queues does not itself implement a window system.

Please note that before Coin 2.3.1, sensors with equal priority (or the same trigger time for SoTimerQueue sensors) were processed LIFO. This has now been changed to FIFO to be conformant to SGI Inventor.

See also
SoSensor SoTimerQueueSensor SoDelayQueueSensor
SoTimerSensor SoAlarmSensor
SoIdleSensor SoDataSensor SoOneShotSensor
SoPathSensor SoFieldSensor SoNodeSensor

Constructor & Destructor Documentation

◆ SoSensorManager()

SoSensorManager::SoSensorManager ( void )

Constructor.

◆ ~SoSensorManager()

SoSensorManager::~SoSensorManager ( )

Destructor.

Member Function Documentation

◆ doSelect()

int SoSensorManager::doSelect ( int nfds,
void * readfds,
void * writefds,
void * exceptfds,
struct timeval * usertimeout )

This method is an unimplemented compatibility stub. It asserts in assertion-enabled builds and otherwise returns zero without waiting for I/O or processing sensors.

Integrate processTimerQueue(), processImmediateQueue() and processDelayQueue() with the application's event loop. Use isTimerSensorPending() to bound the I/O wait by the next absolute sensor deadline, and setChangedCallback() to update the wait when queues change. See the class documentation for the integration sequence and notification limitations.

See also
SoDB::getSensorManager()

◆ getDelaySensorTimeout()

const SbTime & SoSensorManager::getDelaySensorTimeout ( void )

Returns the timeout value for sensors in the delay queue.

See also
setDelaySensorTimeout(), SoDelayQueueSensor

◆ insertDelaySensor()

void SoSensorManager::insertDelaySensor ( SoDelayQueueSensor * newentry)

Add a new entry to the queue of delay sensors.

See also
removeFromQueue()

◆ insertTimerSensor()

void SoSensorManager::insertTimerSensor ( SoTimerQueueSensor * newentry)

Add a new entry to the queue of timer sensors. The queue will be sorted in order of supposed trigger time.

See also
removeFromQueue()

◆ isDelaySensorPending()

SbBool SoSensorManager::isDelaySensorPending ( void )

Returns TRUE if at least one delay sensor or immediate sensor is present in the respective queue, otherwise FALSE.

◆ isTimerSensorPending()

SbBool SoSensorManager::isTimerSensorPending ( SbTime & tm)

Returns TRUE if at least one timer sensor is present in the queue, otherwise FALSE.

If sensors are pending, tm receives the absolute trigger time of the first sensor, in the same time base as SbTime::getTimeOfDay(). It is not a relative interval. For an event-loop timeout, subtract the current time and clamp a negative result to SbTime::zero(). If no timer is pending, tm is left unchanged.

See also
processTimerQueue()

◆ processDelayQueue()

void SoSensorManager::processDelayQueue ( SbBool isidle)

Trigger all delay queue entries in priority order.

The isidle flag indicates whether or not the processing happens because the application is idle or because the delay queue timeout was reached.

A delay queue sensor with priority > 0 can only be triggered once during a call to this function. If a delay sensor is rescheduled during processDelayQueue(), it is not processed until the next time this function is called. This is done to avoid an infinite loop while processing the sensors.

If a sensor callback throws, skipped idle sensors and sensors deferred to the next pass are restored before the exception is propagated.

A delay queue sensor with priority 0 is called an immediate sensor.

See also
SoDB::setDelaySensorTimeout()
SoSensorManager::processImmediateQueue()

◆ processImmediateQueue()

void SoSensorManager::processImmediateQueue ( void )

Process all immediate sensors (delay sensors with priority 0).

Be aware that you might risk an infinite loop using immediate sensors. Unlike delay queue sensors, immediate sensors can be rescheduled and triggered multiple times during immediate queue processing.

See also
SoDelayQueueSensor::setPriority()

◆ processTimerQueue()

void SoSensorManager::processTimerQueue ( void )

Trigger all the timers which have expired.

If a sensor callback throws, recurring timers awaiting rescheduling are restored before the exception is propagated. Timers canceled by the callback remain canceled.

◆ removeDelaySensor()

void SoSensorManager::removeDelaySensor ( SoDelayQueueSensor * entry)

Remove an entry from the queue of prioritized sensors.

See also
addToQueue()

◆ removeRescheduledTimer()

void SoSensorManager::removeRescheduledTimer ( SoTimerQueueSensor * s)

This API member is considered internal to the library, as it is not likely to be of interest to the application programmer.

◆ removeTimerSensor()

void SoSensorManager::removeTimerSensor ( SoTimerQueueSensor * entry)

Remove an entry from the queue of timer sensors.

◆ rescheduleTimer()

void SoSensorManager::rescheduleTimer ( SoTimerSensor * s)

This API member is considered internal to the library, as it is not likely to be of interest to the application programmer.

◆ setChangedCallback()

void SoSensorManager::setChangedCallback ( void(*)(void *) func,
void * data )

Register the callback used to update the application's event-loop timer or request a wakeup when sensor queues change. The callback is invoked synchronously by queue operations; it is not an event loop.

There is one callback slot. A new registration replaces the previous callback and its data. Passing NULL disables the callback. Registering does not invoke it for sensors already pending, so query the queues when setting up the integration.

Notifications are suppressed during processTimerQueue(), processDelayQueue() and processImmediateQueue(). Insertion of a delay sensor with priority zero also does not notify the callback. Recompute pending work after processing queues and dispatching application events. The callback should normally arrange a later processing pass rather than process queues itself.

Queue state is updated before the callback is invoked. If it throws, the exception is propagated and the completed queue operation remains in effect.

See also
isTimerSensorPending(), isDelaySensorPending()

◆ setDelaySensorTimeout()

void SoSensorManager::setDelaySensorTimeout ( const SbTime & t)

Delay sensors are usually triggered only when the system is idle. But when there are continuous updates to the scene graph, there's a possibility that the delay queue will starve and sensors are never triggered. To make sure this won't happen, this is a timeout value for the delay queue. When this timeout has been reached, the sensors in the delay queue gets processed before other sensors and events. This method will let the user set this timeout value.

The default value is 1/12 of a second.

Specifying a zero time will disable the timeout, opening for potential delay queue starvation.

See also
getDelaySensorTimeout(), SoDelayQueueSensor

The documentation for this class was generated from the following files: