1 | package de.uka.ipd.sdq.scheduler.queueing.basicqueues; |
2 | |
3 | import java.util.ArrayList; |
4 | import java.util.Hashtable; |
5 | import java.util.Iterator; |
6 | import java.util.List; |
7 | |
8 | import de.uka.ipd.sdq.scheduler.SchedulerModel; |
9 | import de.uka.ipd.sdq.scheduler.priority.IPriority; |
10 | import de.uka.ipd.sdq.scheduler.priority.IPriorityManager; |
11 | import de.uka.ipd.sdq.scheduler.processes.IActiveProcess; |
12 | import de.uka.ipd.sdq.scheduler.processes.impl.ProcessWithPriority; |
13 | import de.uka.ipd.sdq.scheduler.queueing.IProcessQueue; |
14 | import de.uka.ipd.sdq.scheduler.resources.IResourceInstance; |
15 | |
16 | public class PriorityArray implements IProcessQueue { |
17 | |
18 | private SchedulerModel model; |
19 | private Hashtable<IPriority, IProcessQueue> priorityTable; |
20 | private IPriorityManager priority_manager; |
21 | |
22 | public PriorityArray(SchedulerModel model, IPriorityManager priority_manager) { |
23 | this.model = model; |
24 | this.priority_manager = priority_manager; |
25 | this.priorityTable = new Hashtable<IPriority, IProcessQueue>(); |
26 | for (IPriority prio : priority_manager.decreasing()) { |
27 | priorityTable.put(prio, new ProcessQueueImpl(model)); |
28 | } |
29 | } |
30 | |
31 | /** |
32 | * Returns the number of processes in the priority array. |
33 | */ |
34 | @SuppressWarnings("unchecked") |
35 | public int size() { |
36 | int num = 0; |
37 | for (IProcessQueue queue : priorityTable.values()) { |
38 | num += queue.size(); |
39 | } |
40 | return num; |
41 | } |
42 | |
43 | /** |
44 | * @return True, if the priority array is empty. False, otherwise. |
45 | */ |
46 | @SuppressWarnings("unchecked") |
47 | public boolean isEmpty() { |
48 | for (IProcessQueue queue : priorityTable.values()) { |
49 | if (!queue.isEmpty()) |
50 | return false; |
51 | } |
52 | return true; |
53 | } |
54 | |
55 | /** |
56 | * Removes the given process from the priorityarray. |
57 | * |
58 | * @param process |
59 | * @return True, if the process has been successfully removed. False, |
60 | * otherwise. |
61 | */ |
62 | public boolean remove(IActiveProcess process) { |
63 | return getQueueFor(process).remove(process); |
64 | } |
65 | |
66 | /** |
67 | * Adds a new process at the END of the process' priority's queue. |
68 | * |
69 | * @param process |
70 | */ |
71 | public void addLast(IActiveProcess process) { |
72 | add(process,false); |
73 | } |
74 | |
75 | /** |
76 | * Adds a new process at the BEGINNING of the process' priority's queue. |
77 | * |
78 | * @param process |
79 | */ |
80 | public void addFirst(IActiveProcess process) { |
81 | add(process,true); |
82 | } |
83 | |
84 | public void add(IActiveProcess process, boolean in_front) { |
85 | getQueueFor(process).add(process,in_front); |
86 | } |
87 | |
88 | /** |
89 | * Returns the queue of the process' priority. |
90 | * |
91 | * @param process |
92 | * @return Queue for the given process. |
93 | */ |
94 | private IProcessQueue getQueueFor(IActiveProcess process) { |
95 | assert process instanceof ProcessWithPriority; |
96 | return getQueue( ((ProcessWithPriority)process).getDynamicPriority()); |
97 | } |
98 | |
99 | |
100 | /** |
101 | * @return Returns the queue with the highest priority which is not empty. |
102 | * Null if all queues are empty. |
103 | */ |
104 | private IProcessQueue getNonEmptyQueueWithHighestPriority() { |
105 | for (IPriority prio : priority_manager.decreasing()) { |
106 | if (!getQueue(prio).isEmpty()) |
107 | return getQueue(prio); |
108 | } |
109 | return null; |
110 | } |
111 | |
112 | private IProcessQueue getQueue(IPriority prio) { |
113 | return priorityTable.get(prio); |
114 | } |
115 | |
116 | /** |
117 | * Returns the queue with the highest priority of which at least one process |
118 | * can be executed on instance. |
119 | * |
120 | * @param instance |
121 | * @return |
122 | */ |
123 | @SuppressWarnings("unchecked") |
124 | public IProcessQueue getBestRunnableQueue( |
125 | IResourceInstance instance) { |
126 | IProcessQueue queue = null; |
127 | for (IPriority prio : priority_manager.decreasing()) { |
128 | queue = getQueue(prio).getBestRunnableQueue(instance); |
129 | if (queue != null) break; |
130 | } |
131 | return queue; |
132 | } |
133 | |
134 | /** |
135 | * Returns the process with the highest priority runnable on the given instance. |
136 | * @param instance |
137 | * @return |
138 | */ |
139 | public IActiveProcess getNextRunnableProcess(IResourceInstance instance) { |
140 | IActiveProcess process = null; |
141 | for (IPriority prio : priority_manager.decreasing()) { |
142 | process = getQueue(prio).getNextRunnableProcess(); |
143 | if (process != null) break; |
144 | } |
145 | return process; |
146 | } |
147 | |
148 | public boolean contains(IActiveProcess process) { |
149 | for (IProcessQueue queue : priorityTable.values()) { |
150 | if (queue.contains(process)) |
151 | return true; |
152 | } |
153 | return false; |
154 | } |
155 | |
156 | public IActiveProcess getNextRunnableProcess() { |
157 | IProcessQueue queue = getNonEmptyQueueWithHighestPriority(); |
158 | if (queue != null){ |
159 | return queue.getNextRunnableProcess(); |
160 | } |
161 | return null; |
162 | } |
163 | |
164 | /** |
165 | * Adds processes that do not violate the affinity constraint to the list |
166 | * in the specified direction. |
167 | * |
168 | * @param target_instance |
169 | */ |
170 | public void identifyMovableProcesses( |
171 | IResourceInstance target_instance, boolean prio_increasing, |
172 | boolean queue_ascending, int processes_needed, List<IActiveProcess> process_list){ |
173 | Iterable<IPriority> prio_direction = prio_increasing ? priority_manager.increasing() : priority_manager.decreasing(); |
174 | for (IPriority prio : prio_direction) { |
175 | getQueue(prio).identifyMovableProcesses(target_instance, prio_increasing, queue_ascending, processes_needed, process_list); |
176 | if (process_list.size() >= processes_needed) |
177 | break; |
178 | } |
179 | } |
180 | |
181 | public Iterable<IActiveProcess> ascending() { |
182 | return new Iterable<IActiveProcess>(){ |
183 | public Iterator<IActiveProcess> iterator() { |
184 | return new Iterator<IActiveProcess>(){ |
185 | |
186 | Iterator<IPriority> prio_iterator = priority_manager.increasing().iterator(); |
187 | Iterator<IActiveProcess> queue_iterator = null; |
188 | |
189 | public boolean hasNext() { |
190 | while ((queue_iterator == null || !queue_iterator.hasNext()) && prio_iterator.hasNext()){ |
191 | queue_iterator = getQueue(prio_iterator.next()).ascending().iterator(); |
192 | } |
193 | return (queue_iterator != null && queue_iterator.hasNext()); |
194 | } |
195 | |
196 | public IActiveProcess next() { |
197 | while ((queue_iterator == null || !queue_iterator.hasNext()) && prio_iterator.hasNext()){ |
198 | queue_iterator = getQueue(prio_iterator.next()).ascending().iterator(); |
199 | } |
200 | return queue_iterator == null ? null : queue_iterator.next(); |
201 | } |
202 | |
203 | public void remove() { |
204 | } |
205 | |
206 | }; |
207 | } |
208 | |
209 | }; |
210 | } |
211 | |
212 | public Iterable<IActiveProcess> descending() { |
213 | return new Iterable<IActiveProcess>(){ |
214 | public Iterator<IActiveProcess> iterator() { |
215 | return new Iterator<IActiveProcess>(){ |
216 | |
217 | Iterator<IPriority> prio_iterator = priority_manager.decreasing().iterator(); |
218 | Iterator<IActiveProcess> queue_iterator = null; |
219 | |
220 | public boolean hasNext() { |
221 | while ((queue_iterator == null || !queue_iterator.hasNext()) && prio_iterator.hasNext()){ |
222 | queue_iterator = getQueue(prio_iterator.next()).descending().iterator(); |
223 | } |
224 | return (queue_iterator != null && queue_iterator.hasNext()); |
225 | } |
226 | |
227 | public IActiveProcess next() { |
228 | while ((queue_iterator == null || !queue_iterator.hasNext()) && prio_iterator.hasNext()){ |
229 | queue_iterator = getQueue(prio_iterator.next()).descending().iterator(); |
230 | } |
231 | return queue_iterator == null ? null : queue_iterator.next(); |
232 | } |
233 | |
234 | public void remove() { |
235 | } |
236 | |
237 | }; |
238 | } |
239 | |
240 | }; |
241 | } |
242 | |
243 | public IProcessQueue createNewInstance() { |
244 | return new PriorityArray(model, priority_manager); |
245 | } |
246 | |
247 | public boolean processStarving(double threshold) { |
248 | for(IProcessQueue q : priorityTable.values()){ |
249 | if (q.processStarving(threshold)) |
250 | return true; |
251 | } |
252 | return false; |
253 | } |
254 | |
255 | public double getWaitingTime(IActiveProcess process) { |
256 | return getQueueFor(process).getWaitingTime(process); |
257 | } |
258 | |
259 | public void setWaitingTime(IActiveProcess process, double waiting) { |
260 | getQueueFor(process).setWaitingTime(process, waiting); |
261 | } |
262 | |
263 | public List<IActiveProcess> getStarvingProcesses(double starvationLimit) { |
264 | List<IActiveProcess> result = new ArrayList<IActiveProcess>(); |
265 | for(IProcessQueue q : priorityTable.values()){ |
266 | result.addAll(q.getStarvingProcesses(starvationLimit)); |
267 | } |
268 | return result; |
269 | } |
270 | } |