1 /**************************************************************************\
2 * Copyright (c) Kongsberg Oil & Gas Technologies AS
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 *
12 * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * Neither the name of the copyright holder nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 \**************************************************************************/
32
33 /*!
34 \class SoTimerQueueSensor SoTimerQueueSensor.h Inventor/sensors/SoTimerQueueSensor.h
35 \brief The SoTimerQueueSensor class is the abstract base class for sensors triggering on certain timer events.
36
37 \ingroup sensors
38
39 Timer sensors triggers upon specific points in time.
40
41 This class is an abstract superclass which collects the common
42 interface of the various non-abstract timer sensor classes. See the
43 documentation of the subclasses for information on what ways there
44 are to specify base times, intervals, alarm-style single triggering,
45 repeated triggers, etc.
46
47 Note that Coin timer sensors should in no way be considered "hard
48 real-time". That is, you can \e not expect a timer to always trigger
49 at the exact moment it was set up for. Delays in triggering could be
50 due to other activities in Coin, a task suspended, or heavy load
51 from other applications on the system. These situations could all
52 cause the processing of sensor queues (from SoQt / SoWin / SoXt /
53 whatever) to be slightly delayed, thereby causing delays in timer
54 sensor triggering.
55
56 On modern systems, a timer will usually trigger within a few
57 milliseconds of it's designated time, though.
58
59 If a timer sensor can not trigger at the exact moment it has been
60 scheduled, it will be triggered at the first opportunity after the
61 scheduled time has passed.
62
63 Here's a simple usage example. It's a stand-alone example, which
64 only demonstrates how to set up a repeating timer sensor with a
65 callback:
66
67 \code
68 #include <Inventor/Xt/SoXt.h>
69 #include <Inventor/sensors/SoTimerSensor.h>
70 #include <cstdio>
71
72 static void
73 timeSensorCallback(void * data, SoSensor * sensor)
74 {
75 SbTime time = SbTime::getTimeOfDay();
76 SbString string = time.format("%S.%i");
77 (void)printf("%s\n", string.getString());
78 }
79
80
81 int
82 main(int argc, char ** argv)
83 {
84 SoXt::init("test");
85
86 SoTimerSensor * timeSensor = new SoTimerSensor;
87 timeSensor->setFunction(timeSensorCallback);
88 timeSensor->setBaseTime(SbTime::getTimeOfDay());
89 timeSensor->setInterval(1.0f);
90 timeSensor->schedule();
91
92 SoXt::mainLoop();
93 return 0;
94 }
95 \endcode
96 */
97
98 #include <Inventor/sensors/SoTimerQueueSensor.h>
99 #include <Inventor/SoDB.h>
100 #include <cassert>
101
102 #if COIN_DEBUG
103 #include <Inventor/errors/SoDebugError.h>
104 #endif // COIN_DEBUG
105
106 /*!
107 \var SbBool SoTimerQueueSensor::scheduled
108 \c TRUE if the sensor is currently scheduled.
109 */
110
111
112 /*!
113 Default constructor.
114 */
SoTimerQueueSensor(void)115 SoTimerQueueSensor::SoTimerQueueSensor(void)
116 : scheduled(FALSE)
117 {
118 }
119
120 /*!
121 Constructor taking as arguments the sensor callback function and the
122 userdata which will be passed the callback.
123
124 \sa setFunction(), setData()
125 */
SoTimerQueueSensor(SoSensorCB * func,void * data)126 SoTimerQueueSensor::SoTimerQueueSensor(SoSensorCB * func, void * data)
127 : inherited(func, data), scheduled(FALSE)
128 {
129 }
130
131 /*!
132 Destructor.
133 */
~SoTimerQueueSensor(void)134 SoTimerQueueSensor::~SoTimerQueueSensor(void)
135 {
136 // Note: it won't work to move this to the SoSensor destructor
137 // (where it really belongs), because you can't use pure virtual
138 // methods from a destructor.
139 if (this->isScheduled()) this->unschedule();
140 }
141
142 /*!
143 Returns the time at which the sensor will trigger.
144
145 \sa setTriggerTime()
146 */
147 const SbTime &
getTriggerTime(void) const148 SoTimerQueueSensor::getTriggerTime(void) const
149 {
150 return this->triggertime;
151 }
152
153 /*!
154 Set absolute time at which to trigger sensor.
155
156 \sa getTriggerTime()
157 */
158 void
setTriggerTime(const SbTime & time)159 SoTimerQueueSensor::setTriggerTime(const SbTime & time)
160 {
161 if (time != this->triggertime) {
162 this->triggertime = time;
163 if (this->isScheduled()) {
164 SoSensorManager * sm = SoDB::getSensorManager();
165 sm->removeTimerSensor(this);
166 sm->insertTimerSensor(this);
167 }
168 }
169 }
170
171 // Documented in superclass.
172 void
trigger(void)173 SoTimerQueueSensor::trigger(void)
174 {
175 this->scheduled = FALSE;
176 inherited::trigger();
177 }
178
179 /*!
180 Put the sensor in the global timer queue.
181
182 \sa unschedule(), isScheduled()
183 */
184 void
schedule(void)185 SoTimerQueueSensor::schedule(void)
186 {
187 #if COIN_DEBUG
188 assert(this->scheduled == TRUE || this->scheduled == FALSE);
189 if (this->isScheduled()) {
190 SoDebugError::postWarning("SoTimerQueueSensor::schedule",
191 "already scheduled!");
192 return;
193 }
194 #endif // COIN_DEBUG
195
196 SoDB::getSensorManager()->insertTimerSensor(this);
197 this->scheduled = TRUE;
198 }
199
200 /*!
201 Remove sensor from the timer queue, without triggering it first.
202
203 \sa schedule(), isScheduled()
204 */
205 void
unschedule(void)206 SoTimerQueueSensor::unschedule(void)
207 {
208 #if COIN_DEBUG
209 assert(this->scheduled == TRUE || this->scheduled == FALSE);
210 if (!this->isScheduled()) {
211 SoDebugError::postWarning("SoTimerQueueSensor::unschedule",
212 "not scheduled!");
213 return;
214 }
215 #endif // COIN_DEBUG
216 SoDB::getSensorManager()->removeTimerSensor(this);
217 this->scheduled = FALSE;
218 }
219
220 /*!
221 Check if this sensor is scheduled for triggering.
222
223 \sa schedule(), unschedule()
224 */
225 SbBool
isScheduled(void) const226 SoTimerQueueSensor::isScheduled(void) const
227 {
228 return this->scheduled;
229 }
230
231 SbBool
isBefore(const SoSensor * s) const232 SoTimerQueueSensor::isBefore(const SoSensor * s) const
233 {
234 return (this->triggertime < ((SoTimerQueueSensor *)s)->triggertime);
235 }
236