]> git.mxchange.org Git - simgear.git/blob - simgear/structure/event_mgr.cxx
1ada33c83abcc80190620c9416079df66f704b01
[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     for(int i=0; i<_numEntries; i++) {
63         delete _table[i].timer;
64         _table[i].timer = 0;
65     }
66     _numEntries = 0;
67     delete[] _table;
68     _table = 0;
69     _tableSize = 0;
70 }
71
72 void SGTimerQueue::update(double deltaSecs)
73 {
74     _now += deltaSecs;
75     while(_numEntries && nextTime() <= _now) {
76         SGTimer* t = remove();
77         t->run();
78     }
79 }
80
81 void SGTimerQueue::insert(SGTimer* timer, double time)
82 {
83     if(_numEntries >= _tableSize)
84         growArray();
85
86     _numEntries++;
87     _table[_numEntries-1].pri = -(_now + time);
88     _table[_numEntries-1].timer = timer;
89
90     siftUp(_numEntries-1);
91 }
92
93 SGTimer* SGTimerQueue::remove(SGTimer* t)
94 {
95     int entry;
96     for(entry=0; entry<_numEntries; entry++)
97         if(_table[entry].timer == t)
98             break;
99     if(entry == _numEntries)
100         return 0;
101
102     // Swap in the last item in the table, and sift down
103     swap(entry, _numEntries-1);
104     _numEntries--;
105     siftDown(entry);
106
107     return t;
108 }
109
110 SGTimer* SGTimerQueue::remove()
111 {
112     if(_numEntries == 0) {
113         return 0;
114     } else if(_numEntries == 1) {
115         _numEntries = 0;
116         return _table[0].timer;
117     }
118
119     SGTimer *result = _table[0].timer;
120     _table[0] = _table[_numEntries - 1];
121     _numEntries--;
122     siftDown(0);
123     return result;
124 }
125
126 void SGTimerQueue::siftDown(int n)
127 {
128     // While we have children bigger than us, swap us with the biggest
129     // child.
130     while(lchild(n) < _numEntries) {
131         int bigc = lchild(n);
132         if(rchild(n) < _numEntries && pri(rchild(n)) > pri(bigc))
133             bigc = rchild(n);
134         if(pri(bigc) <= pri(n))
135             break;
136         swap(n, bigc);
137         n = bigc;
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 }