14.3. Other Delay-Queue Sensors

In addition to data sensors, two other types of sensors are added to the delay queue: the SoOneShotSensor SoOneShotSensor SoOneShotSensor and the SoIdleSensor SoIdleSensor SoIdleSensor .

General Sequence for One-Shot and Idle Sensors

The following sequence describes the necessary steps for setting up one-shot and idle sensors:

  1. Construct the sensor.

  2. Set the callback function (see the section called “Callback Function”).

  3. Set the priority of the sensor (see the section called “Priorities”).

  4. Schedule the sensor using the schedule() method.

  5. When you are finished with the sensor, delete it.

Note that these sensors must be scheduled explicitly. Use the unschedule() method to remove a sensor from the queue.

SoOneShotSensor

An SoOneShotSensor SoOneShotSensor SoOneShotSensor invokes its callback once whenever the delayed sensor queue is processed. This sensor is useful for a task that does not need to be performed immediately or for tasks that should not be performed immediately (possibly because they are time-consuming). For example, when handling events for a device that generates events quickly (such as the mouse), you want to be able to process each event quickly so that events don't clog up the event queue. If you know that a certain type of event is time-consuming, you can schedule it with a one-shot sensor. For example:

void handleEvent(SoHandleEventAction *action)
{ 
   //Check for correct event type ...
   .
   .
   .
   // Remember information from event for later processing
   currentMousePosition = event->getPosition();

   // Schedule a one-shot sensor to do hard work later
   SoOneShotSensor oneShot = new SoOneShotSensor(
         OneShotTriggerCallback, NULL);
   oneShot->schedule();
}

void OneShotTriggerCallback(void *userData, SoSensor *) 
{
   // Do lengthy operation based on current mouse position;
}
  
void handleEvent(SoHandleEventAction action)
{ 
   //Check for correct event type ...
   .
   .
   .
   // Remember information from event for later processing
   currentMousePosition = @event.GetPosition();

   // Schedule a one-shot sensor to do hard work later
   SoOneShotSensor oneShot = new SoOneShotSensor();
   oneShot.Action = OneShotTriggerCallback;
   oneShot.Schedule();
}

public void OneShotTriggerCallback(SoSensor s) 
{
   // Do lengthy operation based on current mouse position;
}
  
void handleEvent(SoHandleEventAction action)
{ 
   //Check for correct event type ...
   .
   .
   .
   // Remember information from event for later processing
   currentMousePosition = event.getPosition();

   // Schedule a one-shot sensor to do hard work later
   SoOneShotSensor oneShot = new SoOneShotSensor();
   oneShot.setTask(new OneShotTriggerTask());
   oneShot.schedule();
}


class OneShotTriggerTask implements Runnable
{

  @Override
  public void run()
  {
    // Do lengthy operation based on current mouse position;
  }
}
  

Note that sensors that invoke their callback one time only, such as SoOneShotSensor SoOneShotSensor SoOneShotSensor , SoIdleSensor SoIdleSensor SoIdleSensor , and SoAlarmSensor SoAlarmSensor SoAlarmSensor , continue to exist after their callback has been executed, but they do not trigger again unless they are rescheduled. Use the unschedule() method to stop any sensor from invoking its callback when it is scheduled.

The following example uses an SoOneShotSensor SoOneShotSensor SoOneShotSensor to delay rendering until the CPU is idle.

SoOneShotSensor *renderTask;

void main()
{
   ...
   renderTask = new SoOneShotSensor(doRenderCallback, NULL);
   // ... set up events, UI, which will call changeScene()
   // routine.
}

void changeScene()
{
   // ... change scene graph ...
   renderTask->schedule();
}

void doRenderCallback(void *userData, SoSensor *)
{
   // ... does rendering ...
}
  
SoOneShotSensor renderTask;

public void mainFunction()
{
  ...
  renderTask = new SoOneShotSensor();
  renderTask.Action = doRenderCallback;
   // ... set up events, UI, which will call changeScene()
   // routine.
}

public void changeScene()
{
   // ... change scene graph ...
   renderTask.Schedule();
}

public void doRenderCallback (SoSensor s)
{
   // ... does rendering ...
}
SoOneShotSensor renderTask;

public void mainFunction()
{
  ...
  renderTask = new SoOneShotSensor();
  renderTask.setTask(new doRenderCallback());
  // ... set up events, UI, which will call changeScene()
  // routine.
}

public void changeScene()
{
   // ... change scene graph ...
   renderTask.schedule();
}

class doRenderCallback implements Runnable
{

  @Override
  public void run()
  {
    // ... does rendering ...
  }
}

SoIdleSensor

An SoIdleSensor SoIdleSensor SoIdleSensor invokes its callback once whenever the application is idle (there are no events or timers waiting to be processed). Use an idle sensor for low-priority tasks that should be done only when there is nothing else to do. Call the sensor's schedule() method in its callback function if you want it to go off repeatedly (but beware, since this keeps the CPU constantly busy). Note that idle sensors may never be processed if events or timers happen so often that there is no idle time; see the section called “Processing the Sensor Queues (Advanced) for details.