1 | package de.uka.ipd.sdq.simulation.abstractsimengine.processes; |
2 | |
3 | import java.util.ArrayList; |
4 | import java.util.List; |
5 | |
6 | import org.apache.log4j.Logger; |
7 | |
8 | import de.uka.ipd.sdq.simulation.abstractsimengine.AbstractSimProcessDelegator; |
9 | import de.uka.ipd.sdq.simulation.abstractsimengine.ISimProcess; |
10 | import de.uka.ipd.sdq.simulation.abstractsimengine.ISimProcessListener; |
11 | |
12 | public abstract class SimulatedProcess implements ISimProcess { |
13 | |
14 | public static final Logger logger = Logger.getLogger(SimulatedProcess.class); |
15 | |
16 | /** |
17 | * Current state of this process |
18 | */ |
19 | public ProcessState myProcessState = ProcessState.READY; |
20 | |
21 | /** |
22 | * A list of process listeners getting notifications on resume and suspend |
23 | */ |
24 | protected final List<ISimProcessListener> listeners; |
25 | |
26 | /** |
27 | * Strategy used to suspend threads if requested |
28 | */ |
29 | public final ISimProcessStrategy processStrategy; |
30 | |
31 | /** |
32 | * Default constructor. |
33 | * @param processStrategy |
34 | */ |
35 | public SimulatedProcess(ISimProcessStrategy processStrategy) { |
36 | this.processStrategy = processStrategy; |
37 | this.listeners = new ArrayList<ISimProcessListener>(); |
38 | } |
39 | |
40 | public void startProcess(ISimProcessStrategy processStrategy) { |
41 | Runnable myRunnable = new Runnable() { |
42 | public void run() { |
43 | if (logger.isDebugEnabled()) { |
44 | logger.debug("Starting sim process [ID: " + getAbstractProcess().getId() + "]"); |
45 | } |
46 | actions(); |
47 | // SSJSimProcess.this.processStrategy = null; |
48 | if (logger.isDebugEnabled()) { |
49 | logger.debug("Sim process ended [ID: " + getAbstractProcess().getId() + "]"); |
50 | } |
51 | } |
52 | }; |
53 | |
54 | processStrategy.startProcess(myRunnable); |
55 | } |
56 | |
57 | public void actions() { |
58 | // set state to running and suspended, i.e., return to constructor |
59 | this.myProcessState = ProcessState.RUNNING; |
60 | suspend(); |
61 | |
62 | // execute process's behavior |
63 | getAbstractProcess().lifeCycle(); |
64 | |
65 | // terminate process |
66 | this.myProcessState = ProcessState.TERMINATED; |
67 | processStrategy.finishProcess(); |
68 | } |
69 | |
70 | public boolean isTerminated() { |
71 | return this.myProcessState == ProcessState.TERMINATED; |
72 | } |
73 | |
74 | public void passivate() { |
75 | suspend(); |
76 | } |
77 | |
78 | abstract protected AbstractSimProcessDelegator getAbstractProcess(); |
79 | |
80 | public void suspend() { |
81 | if (this.myProcessState != ProcessState.RUNNING) |
82 | throw new IllegalStateException("Tried to suspend non-running process [" + this.getAbstractProcess().getId() |
83 | + "]"); |
84 | if (logger.isDebugEnabled()) { |
85 | logger.debug("Suspending thread [" + this.getAbstractProcess().getId() + "]"); |
86 | } |
87 | |
88 | // notify listeners of the imminent suspend |
89 | notifyListeners(this, true); |
90 | |
91 | // suspend this process |
92 | this.myProcessState = ProcessState.SUSPENDED; |
93 | processStrategy.suspendProcess(); |
94 | |
95 | // notify listeners of the imminent resume |
96 | notifyListeners(this, false); |
97 | } |
98 | |
99 | protected void resume() { |
100 | if (this.myProcessState != ProcessState.SUSPENDED) |
101 | throw new IllegalStateException("Tried to resume thread which was not suspended [" |
102 | + this.getAbstractProcess().getId() + "]"); |
103 | if (logger.isDebugEnabled()) { |
104 | logger.debug("Resuming thread [" + this.getAbstractProcess().getId() + "]"); |
105 | } |
106 | |
107 | // resume this process |
108 | this.myProcessState = ProcessState.RUNNING; |
109 | processStrategy.resumeProcess(); |
110 | } |
111 | |
112 | public void addProcessListener(ISimProcessListener l) { |
113 | this.listeners.add(l); |
114 | } |
115 | |
116 | public void removeProcessListener(ISimProcessListener l) { |
117 | this.listeners.remove(l); |
118 | } |
119 | |
120 | /** |
121 | * Notifies registered listeners that the given process is about to be suspended or resumed |
122 | * again. |
123 | * |
124 | * @param process |
125 | * the process which is being resumed or suspended |
126 | * @param isSuspending |
127 | * true, if the process is about to be suspended; false, if the process is about to |
128 | * be resumed |
129 | */ |
130 | protected void notifyListeners(ISimProcess process, boolean isSuspending) { |
131 | for (ISimProcessListener l : listeners) { |
132 | if (isSuspending) { |
133 | l.notifySuspending(process); |
134 | } else { |
135 | l.notifyResuming(process); |
136 | } |
137 | } |
138 | } |
139 | |
140 | } |