Subversion Repositories programming

Rev

Rev 416 | Rev 418 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
412 ira 1
/*******************************************************************************
415 ira 2
 * Scheduler.java
412 ira 3
 *
4
 * Holds the Scheduler class, which has a generic scheduler class, from which
5
 * all schedulers should be derived.
6
 *
7
 * Copyright (c) 2006, Ira W. Snyder (devel@irasnyder.com)
8
 *
9
 * Permission is hereby granted, free of charge, to any person obtaining a copy
10
 * of this software and associated documentation files (the "Software"), to deal
11
 * in the Software without restriction, including without limitation the rights
12
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
 * copies of the Software, and to permit persons to whom the Software is
14
 * furnished to do so, subject to the following conditions:
15
 *
16
 * The above copyright notice and this permission notice shall be included in
17
 * all copies or substantial portions of the Software.
18
 *
19
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
25
 * IN THE SOFTWARE.
26
 ******************************************************************************/
27
 
413 ira 28
import java.util.Vector;
29
 
415 ira 30
/**
31
 * Base class for all of the specific Schedulers used in Project #1.
32
 *
33
 * @class CS431 Fall 2006
34
 * @author Ira W. Snyder (devel@irasnyder.com)
35
 */
36
public abstract class Scheduler
412 ira 37
{
417 ira 38
    /** The Processes currently waiting to enter the scheduler */
39
    protected Vector<Process> waiting_queue;
40
 
415 ira 41
    /** The Processes that can currently be scheduled */
413 ira 42
    protected Vector<Process> run_queue;
415 ira 43
 
44
    /** A log of important transitions in the Scheduler */
413 ira 45
    protected Vector<LogEntry> log;
415 ira 46
 
47
    /** The current time in this scheduler */
413 ira 48
    protected int cur_time = 0;
415 ira 49
 
50
    /** The process that is currently running on the CPU */
413 ira 51
    protected Process cur_proc;
52
 
415 ira 53
    /**
54
     * Constructor of the Scheduler class.
55
     */
56
    public Scheduler ()
57
    {
417 ira 58
        this.waiting_queue = new Vector<Process> ();
415 ira 59
        this.run_queue = new Vector<Process> ();
60
        this.log = new Vector<LogEntry> ();
61
    }
62
 
63
    /**
64
     * This method must be overridden by an implementer of a Scheduler. It
65
     * will implement the specific behaivior of the specific Scheduler that
66
     * is being implemented.
67
     *
68
     * @return true if we have more things to do, false if we are done
69
     */
413 ira 70
    protected abstract boolean step ();
71
 
72
    /**
73
     * Add a new process to the run queue.
415 ira 74
     * <p>
413 ira 75
     * If you need to support time-delayed processes, then you must override
76
     * this method, and handle pulling them into the run_queue yourself.
415 ira 77
     *
78
     * @param proc the Process to add
79
     * @param add_time the time that this process should be added to the run queue
413 ira 80
     */
81
    public void addProcess (Process proc, int add_time)
82
    {
417 ira 83
        waiting_queue.add (new Process (proc.name, proc.timeslice, add_time));
413 ira 84
    }
85
 
86
    /**
87
     * Expire the currently running process.
415 ira 88
     * <p>
89
     * This removes the current process from the CPU and re-adds it to the
90
     * run_queue. It also logs the expiration.
413 ira 91
     */
92
    protected void expireCurrent ()
93
    {
94
        assert (cur_proc.time_left > 0);
95
 
96
        cur_proc.finished_at = cur_time;
97
 
98
        run_queue.add (cur_proc);
99
        log.add (new LogEntry (cur_proc, cur_time, LogEntry.MsgType.EXPIRE));
100
        cur_proc = null;
101
    }
102
 
415 ira 103
    /**
104
     * Terminate the currently running process.
105
     * <p>
106
     * This should be called if the process has no time left to run.
107
     */
413 ira 108
    protected void completeCurrent ()
109
    {
110
        assert (cur_proc.time_left == 0);
111
 
112
        cur_proc.finished_at = cur_time;
113
 
114
        log.add (new LogEntry (cur_proc, cur_time, LogEntry.MsgType.COMPLETE));
115
        cur_proc = null;
116
    }
117
 
415 ira 118
    /**
119
     * Move a process from the run_queue to the CPU. This removes it from the
120
     * run_queue. Then it adds a log entry.
417 ira 121
     *
415 ira 122
     * @param proc move this process from the run_queue to the CPU
123
     */
413 ira 124
    protected void startProcess (Process proc)
125
    {
126
        cur_proc = proc;
127
        run_queue.remove (cur_proc);
128
 
129
        log.add (new LogEntry (cur_proc, cur_time, LogEntry.MsgType.START));
130
    }
131
 
415 ira 132
    /**
416 ira 133
     * Run the current process, increment the current time, and update the wait
134
     * times for all of the processes that are waiting.
415 ira 135
     */
413 ira 136
    protected void scheduleCurrent ()
137
    {
416 ira 138
        /* Update the wait times for all waiting processes */
139
        for (Process p : run_queue)
140
            p.time_wait++;
141
 
142
        /* Run the current process for one tick */
413 ira 143
        cur_proc.time_left--;
416 ira 144
 
145
        /* Update the time */
413 ira 146
        cur_time++;
147
    }
148
 
415 ira 149
    /**
417 ira 150
     * Pull any Process that was delayed into the Scheduler if it is the
151
     * appropriate time.
152
     */
153
    protected void queueWaitingProcesses ()
154
    {
155
        Vector<Process> wq_clone = (Vector<Process>)waiting_queue.clone ();
156
 
157
        for (Process p : wq_clone)
158
            if (p.entered_at == cur_time)
159
            {
160
                run_queue.add (p);
161
                waiting_queue.remove (p);
162
            }
163
    }
164
 
165
    /**
166
     * Check if the Scheduler is finished running.
167
     *
168
     * @return true if the scheduler is finished, false otherwise
169
     */
170
    protected boolean schedulerFinished ()
171
    {
172
        if (cur_proc == null && run_queue.isEmpty() && waiting_queue.isEmpty())
173
            return true;
174
 
175
        return false;
176
    }
177
 
178
    /**
415 ira 179
     * Print a Gantt Chart detailing the results of this scheduler's run.
180
     */
414 ira 181
    protected void printGanttChart ()
182
    {
183
        Vector<String> t = new Vector<String> ();
184
        Vector<String> l = new Vector<String> ();
185
 
186
        String timeline = new String();
187
        String labels = new String();
188
        String add1 = new String();
189
        String add2 = new String();
190
 
191
        int exptime = 0;
192
        int templen;
193
 
194
        for (LogEntry e : log)
195
        {
196
            if (e.msg == LogEntry.MsgType.EXPIRE || e.msg == LogEntry.MsgType.COMPLETE)
197
            {
198
                exptime = e.time;
199
                continue;
200
            }
201
 
202
            add1 = "|---" + e.proc.name + "---";
203
            add2 = "" + e.time;
204
 
205
            for (int i=0; add2.length() < add1.length(); i++)
206
                add2 += " ";
207
 
208
            if (timeline.length() + add1.length() > 79)
209
            {
210
                t.add (timeline + "|");
211
                templen = labels.length() - String.valueOf(exptime).length();
212
                labels = labels.substring (0, templen+1) + String.valueOf(exptime);
213
                l.add (labels);
415 ira 214
 
215
                /* Clear the current timeline and labels */
414 ira 216
                timeline = new String();
217
                labels = new String();
218
            }
219
 
220
            timeline += add1;
221
            labels += add2;
222
        }
223
 
224
        /* Done, add the last values of timeline and labels to the Vectors */
225
        t.add (timeline + "|");
226
        templen = labels.length() - String.valueOf(exptime).length();
227
        labels = labels.substring (0, templen+1) + String.valueOf(exptime);
228
        l.add (labels);
229
 
230
        assert (l.size() == t.size());
231
 
232
        for (int i=0; i<l.size(); i++)
233
        {
234
            System.out.println (t.elementAt (i));
235
            System.out.println (l.elementAt (i));
236
            System.out.println ();
237
        }
238
    }
239
 
415 ira 240
    /**
416 ira 241
     * Find the average wait time of processes.
242
     */
243
    protected void printWaitTimes ()
244
    {
245
        int numprocs = 0;
246
        int totalwait = 0;
247
 
248
        for (LogEntry e : log)
249
        {
250
            if (e.msg == LogEntry.MsgType.COMPLETE)
251
            {
252
                numprocs++;
253
                totalwait += e.proc.time_wait;
254
            }
255
        }
256
 
257
        System.out.printf ("Average wait time: %d wait time / %d procs = %.2f\n",
258
                totalwait, numprocs, (float)totalwait / (float)numprocs);
259
    }
260
 
261
    /**
417 ira 262
    * Find the average turnaround time of this scheduler.
263
    * <p>
264
    * Turnaround time is defined as the mean time from submission
265
    * until completion of a process.
266
    */
267
    protected void printTurnaroundTimes ()
268
    {
269
        int totalturnaround = 0;
270
        int totalprocs = 0;
271
 
272
        for (LogEntry e : log)
273
        {
274
            if (e.msg == LogEntry.MsgType.COMPLETE)
275
            {
276
                totalturnaround += (e.proc.finished_at - e.proc.entered_at);
277
                totalprocs++;
278
            }
279
        }
280
        System.out.printf ("Average Turnaround time: %.2f\n",
281
                (float)totalturnaround / (float)totalprocs);
282
    }
283
 
284
    /**
415 ira 285
     * Run the simulation of the scheduler. Note that this only works once,
286
     * if you try to run it twice, it is unlikely that it will work.
287
     */
413 ira 288
    public void run ()
289
    {
290
        /* Keep step()ing until we're done */
291
        while (step ())
292
            ; // do nothing
293
 
414 ira 294
        /* Verbose print of each log entry */
295
        //for (LogEntry e : log)
417 ira 296
        //    System.out.println (e);
413 ira 297
 
414 ira 298
        /* Gantt Chart */
299
        printGanttChart ();
300
 
413 ira 301
        /* Print time taken */
416 ira 302
        printWaitTimes ();
417 ira 303
        printTurnaroundTimes ();
416 ira 304
        System.out.println ("Simulation took " + cur_time + " time units to complete!");
413 ira 305
    }
412 ira 306
}
307
 
308
/* vim: set ts=4 sts=4 sw=4 expandtab: */
309