1 | package de.uka.ipd.sdq.scheduler.resources.active; |
2 | |
3 | import java.util.ArrayList; |
4 | import java.util.List; |
5 | import java.util.Map; |
6 | import java.util.concurrent.ConcurrentHashMap; |
7 | |
8 | import de.uka.ipd.sdq.scheduler.IActiveResource; |
9 | import de.uka.ipd.sdq.scheduler.ISchedulableProcess; |
10 | import de.uka.ipd.sdq.scheduler.SchedulerModel; |
11 | import de.uka.ipd.sdq.scheduler.resources.AbstractSimResource; |
12 | import de.uka.ipd.sdq.scheduler.sensors.IActiveResourceStateSensor; |
13 | |
14 | public abstract class AbstractActiveResource extends AbstractSimResource implements IActiveResource { |
15 | |
16 | private static Map<ISchedulableProcess, AbstractActiveResource> currentResourceTable = new ConcurrentHashMap<ISchedulableProcess, AbstractActiveResource>(); |
17 | |
18 | private List<IActiveResourceStateSensor> observers; |
19 | |
20 | public AbstractActiveResource(SchedulerModel model, int capacity, String name, String id) { |
21 | super(model, capacity, name, id); |
22 | observers = new ArrayList<IActiveResourceStateSensor>(); |
23 | } |
24 | |
25 | public final void process(ISchedulableProcess process, int resourceServiceID, double demand) { |
26 | if (!getModel().getSimulationControl().isRunning()) { |
27 | // Do nothing, but allows calling process to complete |
28 | return; |
29 | } |
30 | |
31 | AbstractActiveResource last = getLastResource(process); |
32 | if (!this.equals(last)) { |
33 | if (last != null) { |
34 | last.dequeue(process); |
35 | } |
36 | this.enqueue(process); |
37 | setLastResource(process, this); |
38 | } |
39 | doProcessing(process, resourceServiceID, demand); |
40 | } |
41 | |
42 | protected abstract void doProcessing(ISchedulableProcess process, int resourceServiceID, |
43 | double demand); |
44 | |
45 | protected abstract void enqueue(ISchedulableProcess process); |
46 | |
47 | protected abstract void dequeue(ISchedulableProcess process); |
48 | |
49 | private static AbstractActiveResource getLastResource( |
50 | ISchedulableProcess process) { |
51 | return currentResourceTable.get(process); |
52 | } |
53 | |
54 | private static void setLastResource(ISchedulableProcess process, |
55 | AbstractActiveResource resource) { |
56 | if (!currentResourceTable.containsKey(process)) { |
57 | process.addTerminatedObserver(resource); |
58 | } |
59 | currentResourceTable.put(process, resource); |
60 | } |
61 | |
62 | public static void cleanProcesses() { |
63 | // Activate all waiting processes to yield process completion |
64 | // Synchronization with process() avoids that processes are added after |
65 | // the activation. |
66 | for (ISchedulableProcess process : currentResourceTable.keySet()) { |
67 | if (!process.isFinished()) { |
68 | //TODO: to avoid exceptions at the end of the simulation, |
69 | // these are being caught here. Maybe something can be fixed |
70 | // in the simulation so that the exception does not occur here. |
71 | try { |
72 | process.activate(); |
73 | } catch (IllegalStateException e) { |
74 | |
75 | } |
76 | } |
77 | } |
78 | |
79 | // assert that all threads have been terminated. |
80 | assert currentResourceTable.size() == 0; |
81 | } |
82 | |
83 | public void notifyTerminated(ISchedulableProcess simProcess) { |
84 | currentResourceTable.remove(simProcess); |
85 | } |
86 | |
87 | |
88 | public void addObserver(IActiveResourceStateSensor observer) { |
89 | this.observers.add(observer); |
90 | } |
91 | |
92 | public void removeObserver(IActiveResourceStateSensor observer) { |
93 | this.observers.remove(observer); |
94 | } |
95 | |
96 | protected void fireStateChange(int state, int instanceId) { |
97 | for (IActiveResourceStateSensor l : observers) { |
98 | l.update(state, instanceId); |
99 | } |
100 | } |
101 | |
102 | protected void fireDemandCompleted(ISchedulableProcess simProcess) { |
103 | for (IActiveResourceStateSensor l : observers) { |
104 | l.demandCompleted(simProcess); |
105 | } |
106 | } |
107 | |
108 | } |