1 //------------------------------------------------------------------------------
2 // emEngine.cpp
3 //
4 // Copyright (C) 2005-2008 Oliver Hamann.
5 //
6 // Homepage: http://eaglemode.sourceforge.net/
7 //
8 // This program is free software: you can redistribute it and/or modify it under
9 // the terms of the GNU General Public License version 3 as published by the
10 // Free Software Foundation.
11 //
12 // This program is distributed in the hope that it will be useful, but WITHOUT
13 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 // FOR A PARTICULAR PURPOSE. See the GNU General Public License version 3 for
15 // more details.
16 //
17 // You should have received a copy of the GNU General Public License version 3
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19 //------------------------------------------------------------------------------
20 
21 #include <emCore/emEngine.h>
22 
23 
emEngine(emScheduler & scheduler)24 emEngine::emEngine(emScheduler & scheduler)
25 	: Scheduler(scheduler)
26 {
27 	Scheduler.EngineCount++;
28 	RNode.Prev=NULL;
29 	RNode.Next=NULL;
30 	SLFirst=NULL;
31 	AwakeState=-1;
32 	Priority=DEFAULT_PRIORITY;
33 	Clock=Scheduler.Clock;
34 }
35 
36 
~emEngine()37 emEngine::~emEngine()
38 {
39 	while (SLFirst) RemoveLink(SLFirst);
40 	if (Scheduler.CurrentEngine==this) Scheduler.CurrentEngine=NULL;
41 	if (AwakeState>=0) {
42 		RNode.Next->Prev=RNode.Prev;
43 		RNode.Prev->Next=RNode.Next;
44 	}
45 	Scheduler.EngineCount--;
46 }
47 
48 
AddWakeUpSignal(const emSignal & signal)49 void emEngine::AddWakeUpSignal(const emSignal & signal)
50 {
51 	emSignal * sig;
52 	emSignal::Link * sl, * el;
53 
54 	sig=(emSignal*)&signal;
55 	sl=SLFirst;
56 	el=sig->ELFirst;
57 	if (sl && el) {
58 		do {
59 			if (sl->Signal==sig) {
60 				sl->RefCount++;
61 				return;
62 			}
63 			sl=sl->SLNext;
64 			if (!sl) break;
65 			if (el->Engine==this) {
66 				el->RefCount++;
67 				return;
68 			}
69 			el=el->ELNext;
70 		} while (el);
71 	}
72 	sl=(emSignal::Link*)malloc(sizeof(emSignal::Link));
73 	sl->Engine=this;
74 	sl->ELThisPtr=&sig->ELFirst;
75 	sl->ELNext=sig->ELFirst;
76 	if (sl->ELNext) sl->ELNext->ELThisPtr=&sl->ELNext;
77 	sig->ELFirst=sl;
78 	sl->Signal=sig;
79 	sl->SLThisPtr=&SLFirst;
80 	sl->SLNext=SLFirst;
81 	if (sl->SLNext) sl->SLNext->SLThisPtr=&sl->SLNext;
82 	SLFirst=sl;
83 	sl->RefCount=1;
84 }
85 
86 
RemoveWakeUpSignal(const emSignal & signal)87 void emEngine::RemoveWakeUpSignal(const emSignal & signal)
88 {
89 	emSignal * sig;
90 	emSignal::Link * sl, * el;
91 
92 	sig=(emSignal*)&signal;
93 	sl=SLFirst;
94 	el=sig->ELFirst;
95 	if (!sl || !el) return;
96 	for (;;) {
97 		if (sl->Signal==sig) {
98 			break;
99 		}
100 		sl=sl->SLNext;
101 		if (!sl) return;
102 		if (el->Engine==this) {
103 			sl=el;
104 			break;
105 		}
106 		el=el->ELNext;
107 		if (!el) return;
108 	}
109 	if (--sl->RefCount>0) return;
110 	RemoveLink(sl);
111 }
112 
113 
GetWakeUpSignalRefs(const emSignal & signal) const114 int emEngine::GetWakeUpSignalRefs(const emSignal & signal) const
115 {
116 	const emSignal::Link * sl, * el;
117 
118 	sl=SLFirst;
119 	el=signal.ELFirst;
120 	if (sl && el) {
121 		do {
122 			if (sl->Signal==&signal) {
123 				return sl->RefCount;
124 			}
125 			sl=sl->SLNext;
126 			if (!sl) break;
127 			if (el->Engine==this) {
128 				return el->RefCount;
129 			}
130 			el=el->ELNext;
131 		} while (el);
132 	}
133 	return 0;
134 }
135 
136 
SetEnginePriority(PriorityType priority)137 void emEngine::SetEnginePriority(PriorityType priority)
138 {
139 	emScheduler::EngineRingNode * l;
140 
141 	if (Priority==priority) return;
142 	Priority=priority;
143 	if (AwakeState<0) return;
144 	RNode.Prev->Next=RNode.Next;
145 	RNode.Next->Prev=RNode.Prev;
146 	l=Scheduler.AwakeLists+(Priority*2+AwakeState);
147 	if (
148 		Scheduler.CurrentAwakeList<l &&
149 		AwakeState==Scheduler.TimeSlice
150 	) Scheduler.CurrentAwakeList=l;
151 	RNode.Next=l;
152 	RNode.Prev=l->Prev;
153 	l->Prev->Next=&RNode;
154 	l->Prev=&RNode;
155 }
156 
157 
WakeUpImp()158 void emEngine::WakeUpImp()
159 {
160 	emScheduler::EngineRingNode * l;
161 
162 	if (AwakeState>=0) {
163 		RNode.Prev->Next=RNode.Next;
164 		RNode.Next->Prev=RNode.Prev;
165 	}
166 	AwakeState=Scheduler.TimeSlice;
167 	l=Scheduler.AwakeLists+(Priority*2+AwakeState);
168 	if (Scheduler.CurrentAwakeList<l) Scheduler.CurrentAwakeList=l;
169 	RNode.Next=l;
170 	RNode.Prev=l->Prev;
171 	l->Prev->Next=&RNode;
172 	l->Prev=&RNode;
173 }
174 
175 
RemoveLink(emSignal::Link * link)176 void emEngine::RemoveLink(emSignal::Link * link)
177 {
178 	*link->SLThisPtr=link->SLNext;
179 	if (link->SLNext) link->SLNext->SLThisPtr=link->SLThisPtr;
180 	*link->ELThisPtr=link->ELNext;
181 	if (link->ELNext) link->ELNext->ELThisPtr=link->ELThisPtr;
182 	free((void*)link);
183 }
184