]> git.mxchange.org Git - simgear.git/blob - simgear/structure/event_mgr.cxx
Add optional attribute condition to "copyProperties".
[simgear.git] / simgear / structure / event_mgr.cxx
1 #include "event_mgr.hxx"
2
3 #include <simgear/math/SGMath.hxx>
4 #include <simgear/debug/logstream.hxx>
5
6 void SGEventMgr::add(const std::string& name, SGCallback* cb,
7                      double interval, double delay,
8                      bool repeat, bool simtime)
9 {
10     // Clamp the delay value to 1 usec, so that user code can use
11     // "zero" as a synonym for "next frame".
12     if(delay <= 0) delay = 0.000001;
13
14     SGTimer* t = new SGTimer;
15     t->interval = interval;
16     t->callback = cb;
17     t->repeat = repeat;
18     t->name = name;
19     
20     SGTimerQueue* q = simtime ? &_simQueue : &_rtQueue;
21
22     q->insert(t, delay);
23 }
24
25 SGTimer::~SGTimer()
26 {
27     delete callback;
28     callback = NULL;
29 }
30
31 void SGTimer::run()
32 {
33     (*callback)();
34 }
35
36 void SGEventMgr::update(double delta_time_sec)
37 {
38     _simQueue.update(delta_time_sec);
39     
40     double rt = _rtProp ? _rtProp->getDoubleValue() : 0;
41     _rtQueue.update(rt);
42 }
43
44 void SGEventMgr::removeTask(const std::string& name)
45 {
46   SGTimer* t = _simQueue.findByName(name);
47   if (t) {
48     _simQueue.remove(t);
49   } else if ((t = _rtQueue.findByName(name))) {
50     _rtQueue.remove(t);
51   } else {
52     SG_LOG(SG_GENERAL, SG_WARN, "removeTask: no task found with name:" << name);
53     return;
54   }
55   
56   delete t;
57 }
58
59 ////////////////////////////////////////////////////////////////////////
60 // SGTimerQueue
61 // This is the priority queue implementation:
62 ////////////////////////////////////////////////////////////////////////
63
64 SGTimerQueue::SGTimerQueue(int size)
65 {
66     _now = 0;
67     _numEntries = 0;
68     _tableSize = 1;
69     while(size > _tableSize)
70         _tableSize = ((_tableSize + 1)<<1) - 1;
71
72     _table = new HeapEntry[_tableSize];
73     for(int i=0; i<_tableSize; i++) {
74         _table[i].pri = 0;
75         _table[i].timer = 0;
76     }
77 }
78
79
80 SGTimerQueue::~SGTimerQueue()
81 {
82     for(int i=0; i<_numEntries; i++) {
83         delete _table[i].timer;
84         _table[i].timer = 0;
85     }
86     _numEntries = 0;
87     delete[] _table;
88     _table = 0;
89     _tableSize = 0;
90 }
91
92 void SGTimerQueue::update(double deltaSecs)
93 {
94     _now += deltaSecs;
95     while(_numEntries && nextTime() <= _now) {
96         SGTimer* t = remove();
97         if(t->repeat)
98             insert(t, t->interval);
99         t->run();
100         if (!t->repeat)
101             delete t;
102     }
103 }
104
105 void SGTimerQueue::insert(SGTimer* timer, double time)
106 {
107     if(_numEntries >= _tableSize)
108         growArray();
109
110     _numEntries++;
111     _table[_numEntries-1].pri = -(_now + time);
112     _table[_numEntries-1].timer = timer;
113
114     siftUp(_numEntries-1);
115 }
116
117 SGTimer* SGTimerQueue::remove(SGTimer* t)
118 {
119     int entry;
120     for(entry=0; entry<_numEntries; entry++)
121         if(_table[entry].timer == t)
122             break;
123     if(entry == _numEntries)
124         return 0;
125
126     // Swap in the last item in the table, and sift down
127     swap(entry, _numEntries-1);
128     _numEntries--;
129     siftDown(entry);
130
131     return t;
132 }
133
134 SGTimer* SGTimerQueue::remove()
135 {
136     if(_numEntries == 0) {
137         return 0;
138     } else if(_numEntries == 1) {
139         _numEntries = 0;
140         return _table[0].timer;
141     }
142
143     SGTimer *result = _table[0].timer;
144     _table[0] = _table[_numEntries - 1];
145     _numEntries--;
146     siftDown(0);
147     return result;
148 }
149
150 void SGTimerQueue::siftDown(int n)
151 {
152     // While we have children bigger than us, swap us with the biggest
153     // child.
154     while(lchild(n) < _numEntries) {
155         int bigc = lchild(n);
156         if(rchild(n) < _numEntries && pri(rchild(n)) > pri(bigc))
157             bigc = rchild(n);
158         if(pri(bigc) <= pri(n))
159             break;
160         swap(n, bigc);
161         n = bigc;
162     }
163 }
164
165 void SGTimerQueue::siftUp(int n)
166 {
167     while((n != 0) && (_table[n].pri > _table[parent(n)].pri)) {
168         swap(n, parent(n));
169         n = parent(n);
170     }
171     siftDown(n);
172 }
173
174 void SGTimerQueue::growArray()
175 {
176     _tableSize = ((_tableSize+1)<<1) - 1;
177     HeapEntry *newTable = new HeapEntry[_tableSize];
178     for(int i=0; i<_numEntries; i++) {
179         newTable[i].pri  = _table[i].pri;
180         newTable[i].timer = _table[i].timer;
181     }
182     delete[] _table;
183     _table = newTable;
184 }
185
186 SGTimer* SGTimerQueue::findByName(const std::string& name) const
187 {
188   for (int i=0; i < _numEntries; ++i) {
189     if (_table[i].timer->name == name) {
190       return _table[i].timer;
191     }
192   }
193   
194   return NULL;
195 }