Subversion Repositories programming

Rev

Rev 413 | Rev 415 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*******************************************************************************
 * File: Scheduler.java
 *
 * Holds the Scheduler class, which has a generic scheduler class, from which
 * all schedulers should be derived.
 *
 * Copyright (c) 2006, Ira W. Snyder (devel@irasnyder.com)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 ******************************************************************************/

import java.util.Vector;

abstract class Scheduler
{
    protected Vector<Process> run_queue;
    protected Vector<LogEntry> log;
    protected int cur_time = 0;
    protected Process cur_proc;

    protected abstract boolean step ();

    /**
     * Add a new process to the run queue.
     *
     * If you need to support time-delayed processes, then you must override
     * this method, and handle pulling them into the run_queue yourself.
     */
    public void addProcess (Process proc, int add_time)
    {
        run_queue.add (new Process(proc));
    }

    /**
     * Expire the currently running process.
     *
     * This removes the current process from the cpu and re-adds it to the
     * run_queue.
     */
    protected void expireCurrent ()
    {
        assert (cur_proc.time_left > 0);

        cur_proc.finished_at = cur_time;

        run_queue.add (cur_proc);
        log.add (new LogEntry (cur_proc, cur_time, LogEntry.MsgType.EXPIRE));
        cur_proc = null;
    }

    protected void completeCurrent ()
    {
        assert (cur_proc.time_left == 0);

        cur_proc.finished_at = cur_time;

        log.add (new LogEntry (cur_proc, cur_time, LogEntry.MsgType.COMPLETE));
        cur_proc = null;
    }

    protected void startProcess (Process proc)
    {
        cur_proc = proc;
        cur_proc.started_at = cur_time;
        run_queue.remove (cur_proc);

        log.add (new LogEntry (cur_proc, cur_time, LogEntry.MsgType.START));
    }

    protected void scheduleCurrent ()
    {
        cur_proc.time_left--;
        cur_time++;
    }

    protected void printGanttChart ()
    {
        Vector<String> t = new Vector<String> ();
        Vector<String> l = new Vector<String> ();

        String timeline = new String();
        String labels = new String();
        String add1 = new String();
        String add2 = new String();

        int exptime = 0;
        int templen;

        for (LogEntry e : log)
        {
            if (e.msg == LogEntry.MsgType.EXPIRE || e.msg == LogEntry.MsgType.COMPLETE)
            {
                exptime = e.time;
                continue;
            }

            add1 = "|---" + e.proc.name + "---";
            add2 = "" + e.time;

            for (int i=0; add2.length() < add1.length(); i++)
                add2 += " ";

            if (timeline.length() + add1.length() > 79)
            {
                t.add (timeline + "|");

                templen = labels.length() - String.valueOf(exptime).length();
                labels = labels.substring (0, templen+1) + String.valueOf(exptime);
                
                l.add (labels);
                timeline = new String();
                labels = new String();
            }

            timeline += add1;
            labels += add2;
        }

        /* Done, add the last values of timeline and labels to the Vectors */
        t.add (timeline + "|");

        templen = labels.length() - String.valueOf(exptime).length();
        labels = labels.substring (0, templen+1) + String.valueOf(exptime);
        l.add (labels);

        assert (l.size() == t.size());

        for (int i=0; i<l.size(); i++)
        {
            System.out.println (t.elementAt (i));
            System.out.println (l.elementAt (i));
            System.out.println ();
        }
    }

    public Scheduler ()
    {
        this.run_queue = new Vector<Process> ();
        this.log = new Vector<LogEntry> ();
    }

    public void run ()
    {
        /* Keep step()ing until we're done */
        while (step ())
            ; // do nothing

        /* Verbose print of each log entry */
        //for (LogEntry e : log)
        //   System.out.println (e);

        /* Gantt Chart */
        printGanttChart ();

        /* Print time taken */
        System.out.println ("\nSimulation took " + cur_time + " time units to complete!");
    }
}

/* vim: set ts=4 sts=4 sw=4 expandtab: */