Package ptolemy.domains.csp.demo.BusContention

Source Code of ptolemy.domains.csp.demo.BusContention.BusContentionApplet$ThreadRenderer

/* A CSP model of hardware bus contention.

Copyright (c) 1999-2006 The Regents of the University of California.
All rights reserved.
Permission is hereby granted, without written agreement and without
license or royalty fees, to use, copy, modify, and distribute this
software and its documentation for any purpose, provided that the above
copyright notice and the following two paragraphs appear in all copies
of this software.

IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.

THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
ENHANCEMENTS, OR MODIFICATIONS.

PT_COPYRIGHT_VERSION_2
COPYRIGHTENDKEY

*/
package ptolemy.domains.csp.demo.BusContention;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.util.HashMap;

import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.border.LineBorder;
import javax.swing.border.TitledBorder;

import ptolemy.actor.TypedCompositeActor;
import ptolemy.actor.gui.PtolemyApplet;
import ptolemy.domains.csp.kernel.CSPDirector;
import ptolemy.kernel.ComponentEntity;
import ptolemy.kernel.util.DebugEvent;
import ptolemy.kernel.util.DebugListener;
import ptolemy.kernel.util.NamedObj;
import ptolemy.kernel.util.Workspace;
import diva.canvas.Figure;
import diva.canvas.Site;
import diva.canvas.connector.Arrowhead;
import diva.canvas.connector.Connector;
import diva.canvas.connector.StraightConnector;
import diva.canvas.interactor.SelectionDragger;
import diva.canvas.toolbox.BasicEllipse;
import diva.canvas.toolbox.BasicFigure;
import diva.canvas.toolbox.BasicRectangle;
import diva.canvas.toolbox.LabelWrapper;
import diva.graph.BasicEdgeController;
import diva.graph.BasicNodeController;
import diva.graph.EdgeRenderer;
import diva.graph.GraphController;
import diva.graph.GraphModel;
import diva.graph.GraphPane;
import diva.graph.JGraph;
import diva.graph.NodeRenderer;
import diva.graph.basic.BasicGraphController;
import diva.graph.basic.BasicGraphModel;
import diva.graph.basic.BasicLayoutTarget;
import diva.graph.layout.LayoutTarget;
import diva.graph.layout.LevelLayout;

//////////////////////////////////////////////////////////////////////////
//// BusContentionApplet

/** A model of hardware subsystems accessing a shared resource using
*  rendezvous. The model shows the use of timed CSP to
*  deterministically handle nondeterministic events.
<p>
*  The applet consists of a controller, three processors and a memory
*  block. At randomly selected points in time, each processor can
*  request permission from the controller to access the memory. The
*  processors each have priorities associated with them, and in cases
*  where there is a simultaneous memory access request, the controller
*  grants permission to the processor with the highest priority.
<p>
*  All communication between actors in a CSP model of computation
*  occurs via rendezvous. Rendezvous is an atomic form of
*  communication. This model uses a timed extension to CSP, so each
*  rendezvous logically occurs at a specific point in time.
<p>
*  Because of the atomic nature of rendezvous, when the controller
*  receives a request for access, it cannot know whether there is
*  another, higher priority request pending at the same time. To
*  overcome this difficulty, an alarm is employed. The alarm is started
*  by the controller immediately following the first request for memory
*  access. It is awakened when time is ready to advance (the model
*  blocks on delays). This indicates to the controller that no more
*  memory requests will occur at the given point in time. Hence, the
*  alarm uses centralized time to make deterministic an inherently
*  non-deterministic activity.
<p>
*  In the applet, each of the initially blue processors (the circular
*  nodes) can be in one of three states. The color yellow indicates
*  that a processor is in state 1 and is waiting for the controller to
*  give it permission to access memory. The color green indicates that
*  a processor has been granted permission to access memory. The color
*  red indicates that the processor has been denied memory access.
*
@author John S. Davis II
@author Michael Shilman
@version $Id: BusContentionApplet.java,v 1.70 2007/12/16 07:29:45 cxh Exp $
@since Ptolemy II 0.3
*  @Pt.ProposedRating Red (eal)
*  @Pt.AcceptedRating Red (cxh)
*/
public class BusContentionApplet extends PtolemyApplet {
    ///////////////////////////////////////////////////////////////////
    ////                         public methods                    ////
    ///////////////////////////////////////////////////////////////////
    ////                         protected methods                 ////

    /** Create a model.
     *  @param workspace The workspace in which to create the model.
     *  @return A model.
     *  @exception Exception If something goes wrong.  This is a broad
     *   exception to allow derived classes wide lattitude as to which
     *   exception to throw.
     */
    protected NamedObj _createModel(Workspace workspace) throws Exception {
        TypedCompositeActor toplevel = new TypedCompositeActor(workspace);
        _toplevel = toplevel;
        toplevel.setName("BusContention");
        new CSPDirector(toplevel, "CSPDirector");

        // Instantiate Actors
        _contentionActor = new Controller(toplevel, "controller");
        _alarmActor = new ContentionAlarm(toplevel, "alarm");
        _memoryActor = new Memory(toplevel, "memory");
        _processActor1 = new Processor(toplevel, "proc1", 1);
        _processActor2 = new Processor(toplevel, "proc2", 2);
        _processActor3 = new Processor(toplevel, "proc3", 3);

        // Set up connections
        toplevel.connect(_contentionActor.requestInput,
                _processActor1.requestOutput);
        toplevel.connect(_contentionActor.requestInput,
                _processActor2.requestOutput);
        toplevel.connect(_contentionActor.requestInput,
                _processActor3.requestOutput);
        toplevel.connect(_contentionActor.contendOutput, _alarmActor.input);
        toplevel.connect(_contentionActor.contendInput, _alarmActor.output);
        toplevel.connect(_contentionActor.requestOutput,
                _processActor1.requestInput);
        toplevel.connect(_contentionActor.requestOutput,
                _processActor2.requestInput);
        toplevel.connect(_contentionActor.requestOutput,
                _processActor3.requestInput);
        toplevel.connect(_memoryActor.output, _processActor1.memoryInput);
        toplevel.connect(_memoryActor.output, _processActor2.memoryInput);
        toplevel.connect(_memoryActor.output, _processActor3.memoryInput);
        toplevel.connect(_memoryActor.input, _processActor1.memoryOutput);
        toplevel.connect(_memoryActor.input, _processActor2.memoryOutput);
        toplevel.connect(_memoryActor.input, _processActor3.memoryOutput);
        return toplevel;
    }

    /** Create an animation pane.
     */
    protected void _createView() {
        super._createView();

        _divaPanel = new JPanel(new BorderLayout());
        _divaPanel.setBorder(new TitledBorder(new LineBorder(Color.black),
                "Animation"));
        _divaPanel.setBackground(getBackground());
        _divaPanel.setPreferredSize(new Dimension(500, 450));
        _divaPanel.setBackground(getBackground());
        getContentPane().add(_divaPanel, BorderLayout.SOUTH);

        _graph = _constructGraph();

        // display the graph.
        final GraphController gc = new BusContentionGraphController();

        final GraphPane gp = new GraphPane(gc, _graph);
        _jgraph = new JGraph(gp);
        _jgraph.repaint();

        // Adding it to the center so that it fills the containing panel.
        _divaPanel.add(_jgraph, BorderLayout.CENTER);

        _jgraph.setBackground(getBackground());

        StateListener listener = new StateListener((GraphPane) _jgraph
                .getCanvasPane());
        _processActor1.addDebugListener(listener);
        _processActor2.addDebugListener(listener);
        _processActor3.addDebugListener(listener);
    }

    /** Override the baseclass start method so that the model
     *  does not immediately begin executing as soon as the
     *  the applet page is displayed. Execution begins once
     *  the "Go" button is depressed. Layout the graph visualization,
     *  since this can't be done in the init method, because the graph
     *  hasn't yet been displayed.
     */
    public void start() {
        _doLayout(_graph, _jgraph.getGraphPane());
    }

    ///////////////////////////////////////////////////////////////////
    ////                         private methods                   ////

    /** Construct the graph representing the topology.
     *  This is sort of bogus because it's totally hard-wired,
     *  but it will do for now...
     */
    private BasicGraphModel _constructGraph() {
        BasicGraphModel model = new BasicGraphModel();
        Object root = model.getRoot();

        // Nodes, with user object set to the actor
        Object n1 = model.createNode(_contentionActor);
        Object n2 = model.createNode(_alarmActor);
        Object n3 = model.createNode(_memoryActor);
        Object n4 = model.createNode(_processActor1);
        Object n5 = model.createNode(_processActor2);
        Object n6 = model.createNode(_processActor3);

        model.addNode(this, n1, root);
        model.addNode(this, n2, root);
        model.addNode(this, n3, root);
        model.addNode(this, n4, root);
        model.addNode(this, n5, root);
        model.addNode(this, n6, root);

        _nodeMap.put(_contentionActor, n1);
        _nodeMap.put(_alarmActor, n2);
        _nodeMap.put(_memoryActor, n3);
        _nodeMap.put(_processActor1, n4);
        _nodeMap.put(_processActor2, n5);
        _nodeMap.put(_processActor3, n6);

        // Edges
        Object e;

        e = model.createEdge(null);
        model.setEdgeHead(this, e, n1);
        model.setEdgeTail(this, e, n2);

        e = model.createEdge(null);
        model.setEdgeHead(this, e, n1);
        model.setEdgeTail(this, e, n4);

        e = model.createEdge(null);
        model.setEdgeHead(this, e, n1);
        model.setEdgeTail(this, e, n5);

        e = model.createEdge(null);
        model.setEdgeHead(this, e, n1);
        model.setEdgeTail(this, e, n6);

        e = model.createEdge(null);
        model.setEdgeHead(this, e, n3);
        model.setEdgeTail(this, e, n4);

        e = model.createEdge(null);
        model.setEdgeHead(this, e, n3);
        model.setEdgeTail(this, e, n5);

        e = model.createEdge(null);
        model.setEdgeHead(this, e, n3);
        model.setEdgeTail(this, e, n6);

        return model;
    }

    /** Layout the graph again.
     */
    private void _doLayout(GraphModel graph, GraphPane gp) {
        // Do the layout
        try {
            final GraphModel layoutGraph = graph;
            final GraphController gc = gp.getGraphController();
            final GraphPane pane = gp;
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    // Layout is a bit stupid
                    LayoutTarget target = new BasicLayoutTarget(gc);
                    LevelLayout staticLayout = new LevelLayout(target);
                    staticLayout.setOrientation(LevelLayout.HORIZONTAL);
                    staticLayout.layout(layoutGraph.getRoot());
                    pane.repaint();
                }
            });
        } catch (Exception e) {
            System.out.println(e);
        }
    }

    ///////////////////////////////////////////////////////////////////
    ////                         private variables                 ////
    // The Actors
    Controller _contentionActor;

    ContentionAlarm _alarmActor;

    Memory _memoryActor;

    Processor _processActor1;

    Processor _processActor2;

    Processor _processActor3;

    // The mapping from Ptolemy actors to graph nodes
    private HashMap _nodeMap = new HashMap();

    // The JGraph where we display stuff
    private JGraph _jgraph;

    // The Diva panel where we display stuff
    private JPanel _divaPanel;

    // The Diva graph
    private BasicGraphModel _graph;

    ///////////////////////////////////////////////////////////////////
    ////                         inner classes                     ////
    ///////////////////////////////////////////////////////////////////
    //// LayoutListener
    // private class LayoutListener implements ActionListener {
    //    public void actionPerformed(ActionEvent evt) {
    //        final GraphPane gp = (GraphPane)_jgraph.getCanvasPane();
    //        final GraphModel g = _graph;
    //        _doLayout(g, gp);
    //    }
    //}
    ///////////////////////////////////////////////////////////////////
    //// BusContentionGraphController
    public class BusContentionGraphController extends BasicGraphController {
        private SelectionDragger _selectionDragger;

        /**
         * Create a new basic controller with default
         * node and edge interactors.
         */
        public BusContentionGraphController() {
            // The interactors attached to nodes and edges
            setNodeController(new BasicNodeController(this));
            setEdgeController(new BasicEdgeController(this));
            getNodeController().setNodeRenderer(new ThreadRenderer(this));
            getEdgeController().setEdgeRenderer(new LocalEdgeRenderer());
        }

        /**
         * Initialize all interaction on the graph pane. This method
         * is called by the setGraphPane() method of the superclass.
         * This initialization cannot be done in the constructor because
         * the controller does not yet have a reference to its pane
         * at that time.
         */
        protected void initializeInteraction() {
            GraphPane pane = getGraphPane();

            // Create and set up the selection dragger
            _selectionDragger = new SelectionDragger(pane);
            _selectionDragger.addSelectionModel(getSelectionModel());
        }
    }

    ///////////////////////////////////////////////////////////////////
    //// LocalEdgeRenderer

    /**
     * LocalEdgeRenderer draws arrowheads on both ends of the connector
     */
    public static class LocalEdgeRenderer implements EdgeRenderer {
        // FindBugs suggests making this class static so as to decrease
        // the size of instances and avoid dangling references.

        /**
         * Render the edge
         */
        public Connector render(Object edge, Site tailSite, Site headSite) {
            StraightConnector c = new StraightConnector(tailSite, headSite);

            // Create an arrow at the head
            Arrowhead headArrow = new Arrowhead(headSite.getX(), headSite
                    .getY(), headSite.getNormal());
            c.setHeadEnd(headArrow);

            // Create an arrow at the tail
            Arrowhead tailArrow = new Arrowhead(tailSite.getX(), tailSite
                    .getY(), tailSite.getNormal());
            c.setTailEnd(tailArrow);

            c.setUserObject(edge);
            return c;
        }
    }

    ///////////////////////////////////////////////////////////////////
    //// StateListener

    /**
     * StateListener is an inner class that listens to state
     * events on the Ptolemy kernel and changes the color of
     * the nodes appropriately.
     */
    public class StateListener implements DebugListener {
        // The Pane
        GraphPane _graphPane;

        /** Create a listener on the given graph pane
         */
        public StateListener(GraphPane pane) {
            _graphPane = pane;
        }

        /** Ignore messages.
         */
        public void message(String message) {
        }

        /** React to the given event.
         */
        public void event(DebugEvent debugEvent) {
            // only trap ExecEvents.
            if (!(debugEvent instanceof ExecEvent)) {
                return;
            }

            ExecEvent event = (ExecEvent) debugEvent;
            final ExecEvent.ExecEventType state = event.getState();
            NamedObj actor = event.getSource();

            // Get the corresponding graph node and its figure
            Object node = _nodeMap.get(actor);
            LabelWrapper wrapper = (LabelWrapper) _graphPane
                    .getGraphController().getFigure(node);
            final BasicFigure figure = (BasicFigure) wrapper.getChild();

            // Color the graph
            try {
                // Used to use invokeAndWait() here, but this leads to deadlock!
                SwingUtilities.invokeLater(new Runnable() {
                    public void run() {
                        if (state == ExecEvent.WAITING) {
                            figure.setFillPaint(Color.yellow);
                        } else if (state == ExecEvent.ACCESSING) {
                            figure.setFillPaint(Color.green);
                        } else if (state == ExecEvent.BLOCKED) {
                            figure.setFillPaint(Color.red);
                        } else {
                            System.err.println("Unknown state: " + state);
                        }
                    }
                });
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    ///////////////////////////////////////////////////////////////////
    //// ThreadRenderer

    /**
     * ThreadRenderer draws the nodes to represent running threads.
     */
    public static class ThreadRenderer implements NodeRenderer {
        // FindBugs suggests making this class static so as to decrease
        // the size of instances and avoid dangling references.

        /** The rectangle size
         */
        private double _size = 50;

        /** The graph controller
         */
        private GraphController _controller;

        public ThreadRenderer(GraphController controller) {
            _controller = controller;
        }

        /**
         * Return the rendered visual representation of this node.
         */
        public Figure render(Object n) {
            ComponentEntity actor = (ComponentEntity) _controller
                    .getGraphModel().getSemanticObject(n);

            boolean isEllipse = actor instanceof Controller
                    || actor instanceof Memory
                    || actor instanceof ContentionAlarm;

            BasicFigure f;

            if (isEllipse) {
                f = new BasicEllipse(0, 0, _size, _size);
            } else {
                f = new BasicRectangle(0, 0, _size, _size);
                f.setFillPaint(Color.blue);
            }

            String label = actor.getName();
            LabelWrapper w = new LabelWrapper(f, label);
            w.setAnchor(SwingConstants.SOUTH);
            w.getLabel().setAnchor(SwingConstants.NORTH);
            return w;
        }
    }
}
TOP

Related Classes of ptolemy.domains.csp.demo.BusContention.BusContentionApplet$ThreadRenderer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.