Subversion Repositories programming

Rev

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);
418 ira 162
                log.add (new LogEntry (p, cur_time, LogEntry.MsgType.ADDED));
417 ira 163
            }
164
    }
165
 
166
    /**
167
     * Check if the Scheduler is finished running.
168
     *
169
     * @return true if the scheduler is finished, false otherwise
170
     */
171
    protected boolean schedulerFinished ()
172
    {
173
        if (cur_proc == null && run_queue.isEmpty() && waiting_queue.isEmpty())
174
            return true;
175
 
176
        return false;
177
    }
178
 
179
    /**
415 ira 180
     * Print a Gantt Chart detailing the results of this scheduler's run.
181
     */
414 ira 182
    protected void printGanttChart ()
183
    {
419 ira 184
        GanttChart gc = new GanttChart (log);
185
        gc.printGanttChart ();
414 ira 186
    }
187
 
415 ira 188
    /**
416 ira 189
     * Find the average wait time of processes.
190
     */
191
    protected void printWaitTimes ()
192
    {
193
        int numprocs = 0;
194
        int totalwait = 0;
195
 
196
        for (LogEntry e : log)
197
        {
198
            if (e.msg == LogEntry.MsgType.COMPLETE)
199
            {
200
                numprocs++;
201
                totalwait += e.proc.time_wait;
202
            }
203
        }
204
 
205
        System.out.printf ("Average wait time: %d wait time / %d procs = %.2f\n",
206
                totalwait, numprocs, (float)totalwait / (float)numprocs);
207
    }
208
 
209
    /**
417 ira 210
    * Find the average turnaround time of this scheduler.
211
    * <p>
212
    * Turnaround time is defined as the mean time from submission
213
    * until completion of a process.
214
    */
215
    protected void printTurnaroundTimes ()
216
    {
217
        int totalturnaround = 0;
218
        int totalprocs = 0;
219
 
220
        for (LogEntry e : log)
221
        {
222
            if (e.msg == LogEntry.MsgType.COMPLETE)
223
            {
224
                totalturnaround += (e.proc.finished_at - e.proc.entered_at);
225
                totalprocs++;
226
            }
227
        }
228
        System.out.printf ("Average Turnaround time: %.2f\n",
229
                (float)totalturnaround / (float)totalprocs);
230
    }
231
 
232
    /**
415 ira 233
     * Run the simulation of the scheduler. Note that this only works once,
234
     * if you try to run it twice, it is unlikely that it will work.
235
     */
413 ira 236
    public void run ()
237
    {
238
        /* Keep step()ing until we're done */
239
        while (step ())
240
            ; // do nothing
241
 
414 ira 242
        /* Verbose print of each log entry */
243
        //for (LogEntry e : log)
417 ira 244
        //    System.out.println (e);
413 ira 245
 
414 ira 246
        /* Gantt Chart */
247
        printGanttChart ();
248
 
413 ira 249
        /* Print time taken */
416 ira 250
        printWaitTimes ();
417 ira 251
        printTurnaroundTimes ();
416 ira 252
        System.out.println ("Simulation took " + cur_time + " time units to complete!");
413 ira 253
    }
412 ira 254
}
255
 
256
/* vim: set ts=4 sts=4 sw=4 expandtab: */
257