]> git.mxchange.org Git - simgear.git/blob - simgear/structure/event_mgr.cxx
Portability fix
[simgear.git] / simgear / structure / event_mgr.cxx
1 #include "event_mgr.hxx"
2
3 void SGEventMgr::add(SGCallback* cb,
4                      double interval, double delay,
5                      bool repeat, bool simtime)
6 {
7     SGTimer* t = new SGTimer;
8     t->interval = interval;
9     t->callback = cb;
10     t->mgr = this;
11     t->repeat = repeat;
12     t->simtime = simtime;
13
14     SGTimerQueue* q = simtime ? &_simQueue : &_rtQueue;
15
16     q->insert(t, delay);
17 }
18
19 void SGTimer::run()
20 {
21     (*callback)();
22
23     if(repeat) {
24         SGTimerQueue* q = simtime ? &mgr->_simQueue : &mgr->_rtQueue;
25         q->insert(this, interval);
26     } else {
27         delete callback;
28         delete this;
29     }
30 }
31
32 void SGEventMgr::update(double delta_time_sec)
33 {
34     _rtQueue.update(delta_time_sec);
35     if(!_freezeProp || _freezeProp->getBoolValue() == false)
36         _simQueue.update(delta_time_sec);
37 }
38
39 ////////////////////////////////////////////////////////////////////////
40 // SGTimerQueue
41 // This is the priority queue implementation:
42 ////////////////////////////////////////////////////////////////////////
43
44 SGTimerQueue::SGTimerQueue(int size)
45 {
46     _now = 0;
47     _numEntries = 0;
48     _tableSize = 1;
49     while(size > _tableSize)
50         _tableSize = ((_tableSize + 1)<<1) - 1;
51
52     _table = new HeapEntry[_tableSize];
53     for(int i=0; i<_tableSize; i++) {
54         _table[i].pri = 0;
55         _table[i].timer = 0;
56     }
57 }
58
59
60 SGTimerQueue::~SGTimerQueue()
61 {
62     delete[] _table;
63 }
64
65 void SGTimerQueue::update(double deltaSecs)
66 {
67     _now += deltaSecs;
68     while(_numEntries && nextTime() <= _now) {
69         SGTimer* t = remove();
70         t->run();
71     }
72 }
73
74 void SGTimerQueue::insert(SGTimer* timer, double time)
75 {
76     if(time < 0) *(int*)0=0;
77
78     if(_numEntries >= _tableSize)
79         growArray();
80
81     _numEntries++;
82     _table[_numEntries-1].pri = -(_now + time);
83     _table[_numEntries-1].timer = timer;
84
85     siftUp(_numEntries-1);
86 }
87
88 SGTimer* SGTimerQueue::remove(SGTimer* t)
89 {
90     int entry;
91     for(entry=0; entry<_numEntries; entry++)
92         if(_table[entry].timer == t)
93             break;
94     if(entry == _numEntries)
95         return 0;
96
97     // Swap in the last item in the table, and sift down
98     swap(entry, _numEntries-1);
99     _numEntries--;
100     siftDown(entry);
101
102     return t;
103 }
104
105 SGTimer* SGTimerQueue::remove()
106 {
107     if(_numEntries == 0) {
108         return 0;
109     } else if(_numEntries == 1) {
110         _numEntries = 0;
111         return _table[0].timer;
112     }
113
114     SGTimer *result = _table[0].timer;
115     _table[0] = _table[_numEntries - 1];
116     _numEntries--;
117     siftDown(0);
118     return result;
119 }
120
121 void SGTimerQueue::siftDown(int n)
122 {
123     // While we have a child bigger than us:
124     while(((lchild(n) < (_numEntries-1))
125            && (_table[n].pri < _table[lchild(n)].pri))
126           ||
127           ((rchild(n) < (_numEntries-1))
128            && (_table[n].pri < _table[rchild(n)].pri)))
129     {
130         // Swap us with the biggest child
131         if(_table[lchild(n)].pri > _table[rchild(n)].pri) {
132             swap(n, lchild(n)); 
133             n = lchild(n);
134         } else {
135             swap(n, rchild(n));
136             n = rchild(n);
137         }
138     }
139 }
140
141 void SGTimerQueue::siftUp(int n)
142 {
143     while((n != 0) && (_table[n].pri > _table[parent(n)].pri)) {
144         swap(n, parent(n));
145         n = parent(n);
146     }
147     siftDown(n);
148 }
149
150 void SGTimerQueue::growArray()
151 {
152     _tableSize = ((_tableSize+1)<<1) - 1;
153     HeapEntry *newTable = new HeapEntry[_tableSize];
154     for(int i=0; i<_numEntries; i++) {
155         newTable[i].pri  = _table[i].pri;
156         newTable[i].timer = _table[i].timer;
157     }
158     delete[] _table;
159     _table = newTable;
160 }