home *** CD-ROM | disk | FTP | other *** search
/ Java 1.2 How-To / JavaHowTo.iso / javafile / ch04 / SyncCode.java < prev    next >
Encoding:
Java Source  |  1998-12-14  |  6.6 KB  |  343 lines

  1. import java.awt.*;
  2. import java.applet.Applet;
  3.  
  4. /*
  5.  * a class for handling first in, first out data structure
  6.  */
  7. class FIFO {
  8.  
  9. /*
  10.  * the maximum depth of the FIFO
  11.  */
  12. final int MaxDepth = 200;
  13.  
  14. /*
  15.  * the real depth of this FIFO
  16.  */
  17. int depth;
  18.  
  19. /*
  20.  * write and read indexes into the data array
  21.  */
  22. int writeIndex;
  23. int readIndex;
  24.  
  25. /*
  26.  * the number of data items currently in the FIFO
  27.  */
  28. int nItems;
  29.  
  30. /*
  31.  * the data proper
  32.  */
  33. int data[] = new int[MaxDepth];
  34.  
  35. /*
  36.  * width and height of the FIFO graphical display
  37.  */
  38. int width;
  39. int height;
  40.  
  41. /*
  42.  * x and y position of the upper-left corner of the FIFO
  43.  * graphical display
  44.  */
  45. int xpos;
  46. int ypos;
  47.  
  48. /**
  49.  * the constructor
  50.  * @param d - depth of the FIFO
  51.  */
  52. public FIFO (int d) {
  53.  
  54.        depth = d;
  55.        writeIndex = 0;
  56.        readIndex = 0;
  57.        nItems = 0;
  58.  
  59.        width = depth + 4;
  60.        height = 50;
  61.        xpos = 50;
  62.        ypos = 75; 
  63. }
  64.  
  65. /**
  66.  * write one integer value into the FIFO
  67.  * @param value - the value to write
  68.  */
  69. void write (int value) {
  70.  
  71.        if (nItems >= depth) return;
  72.  
  73.        data[writeIndex] = value;
  74.        writeIndex += 1;
  75.        writeIndex %= depth;
  76.        nItems += 1;
  77. }
  78.  
  79. /**
  80.  * read one integer value from the FIFO
  81.  */
  82. int read () {
  83.  
  84.        if (nItems < 1) return 0;
  85.  
  86.        int value = data[readIndex];
  87.        readIndex += 1;
  88.        readIndex %= depth;
  89.        nItems -= 1;
  90.  
  91.        return value;
  92. }
  93.  
  94. /**
  95.  * returns true if the FIFO is empty
  96.  */
  97. boolean empty () {
  98.  
  99.        return nItems > 0 ? false : true;
  100. }
  101.  
  102. /**
  103.  * returns true if the FIFO is half full
  104.  */
  105. boolean halfFull () {
  106.  
  107.        return nItems > (depth >> 1) ? true : false;
  108. }
  109.  
  110. /**
  111.  * returns true if the FIFO is full
  112.  */
  113. boolean full () {
  114.  
  115.        return nItems >= (depth) ? true : false;
  116. }
  117.  
  118. /**
  119.  * draws the FIFO graphical display
  120.  * @param g - destination graphics context
  121.  */
  122. void paint (Graphics g) {
  123.  
  124.        int x, y, w, h;
  125.  
  126.        g.setColor (Color.white);
  127.        g.fillRect (xpos, ypos, width, height);
  128.        g.setColor (Color.black);
  129.        g.drawRect (xpos, ypos, width, height);
  130.  
  131.        x = writeIndex + xpos + 2;
  132.        y = ypos - 22;
  133.        g.drawLine (x, y, x, y + 20);
  134.        g.drawString ("Write index "+writeIndex, x+2, y+10);
  135.  
  136.        x = readIndex + xpos + 2;
  137.        y = ypos + height + 22;
  138.        g.drawLine (x, y-20, x, y);
  139.        g.drawString ("Read index "+readIndex, x+2, y);
  140.  
  141.        if (nItems < 1) return;
  142.  
  143.        if (nItems > (depth>>1)) g.setColor (Color.red);
  144.        else g.setColor (Color.green);
  145.  
  146.        x = xpos + 2 + readIndex;
  147.        y = ypos + 2;
  148.        if (writeIndex > readIndex) w = nItems;
  149.        else w = width - readIndex - 4;
  150.        h = height - 4;
  151.        g.fillRect (x, y, w, h);
  152.  
  153.        if (writeIndex > readIndex) return;
  154.  
  155.        x = xpos + 2;
  156.        w = writeIndex;
  157.        g.fillRect (x, y, w, h);
  158. }
  159. }
  160.  
  161. /*
  162.  * a class that generates data continuously
  163.  */
  164. class Source extends Thread {
  165.  
  166. /*
  167.  * the FIFO to write into
  168.  */
  169. FIFO fifo;
  170. int value;
  171.  
  172. /**
  173.  * constructor
  174.  * saves the FIFO instance and starts the thread
  175.  * @param f - an instance of FIFO
  176.  */
  177. public Source (FIFO f) {
  178.  
  179.        fifo = f;
  180.        value = 0;
  181.  
  182.        start ();
  183. }
  184.  
  185. /*
  186.  * the thread that writes one word every 100ms
  187.  */
  188. public void run () {
  189.  
  190.        while (true) {
  191.               synchronized (fifo) {
  192.                      if (fifo.full() == false)
  193.                             fifo.write (value++);
  194.               }
  195.               try {
  196.                      Thread.sleep (100);
  197.               } catch (InterruptedException e) {
  198.               }
  199.        }
  200. }
  201. }
  202.  
  203. /*
  204.  * a class that reads data from the FIFO
  205.  */
  206. class Sink extends Thread {
  207.  
  208. /*
  209.  * the FIFO to read from
  210.  */
  211. FIFO fifo;
  212. int value;
  213.  
  214. /**
  215.  * constructor
  216.  * saves the FIFO instance and starts the thread
  217.  * @param f - an instance of FIFO
  218.  */
  219. public Sink (FIFO f) {
  220.  
  221.        fifo = f;
  222.  
  223.        start ();
  224. }
  225.  
  226. /*
  227.  * the thread that reads all data out after the FIFO is half
  228.  * full
  229.  */
  230. public void run () {
  231.  
  232.        boolean empty;
  233.        boolean halfFull;
  234.  
  235.        while (true) {
  236.               synchronized (fifo) {
  237.                      halfFull = fifo.halfFull ();
  238.               }
  239.               if (halfFull) {
  240.                      try {
  241.                             Thread.sleep (1000);
  242.                      } catch (InterruptedException e) {
  243.                      }
  244.                      do {
  245.                             synchronized (fifo) {
  246.                                    value = fifo.read ();
  247.                             }
  248.                             try {
  249.                                    Thread.sleep (50);
  250.                             } catch (InterruptedException e) {
  251.                             }
  252.                             synchronized (fifo) {
  253.                                    empty = fifo.empty ();
  254.                             }
  255.                      } while (empty == false); 
  256.               }
  257.  
  258.               try {
  259.                      Thread.sleep (100);
  260.               } catch (InterruptedException e) {
  261.               }
  262.        }
  263. }
  264. }
  265.  
  266. /*
  267.  * the applet/application class
  268.  */
  269. public class SyncCode extends Applet implements Runnable {
  270.  
  271. Source source;
  272. Sink sink;
  273. FIFO fifo;
  274. Thread thread;
  275.  
  276. /*
  277.  * called when the applet is loaded
  278.  * create instances of FIFO, Source, Sink, and Thread
  279.  */
  280. public void init () {
  281.  
  282.        fifo = new FIFO (200);
  283.        source = new Source (fifo);
  284.        sink = new Sink (fifo);
  285.  
  286.        thread = new Thread (this);
  287. }
  288.  
  289. /*
  290.  * start the graphics update thread
  291.  */
  292. public void start () {
  293.  
  294.        thread.start ();
  295. }
  296.  
  297.  
  298. /*
  299.  * the graphics update thread
  300.  * call repaint every 100ms
  301.  */
  302. public void run () {
  303.  
  304.        while (true) {
  305.               repaint ();
  306.               try {
  307.                      Thread.sleep (100);
  308.               } catch (InterruptedException e) {
  309.               }
  310.        }
  311. }
  312.  
  313. /**
  314.  * called from update() in response to repaint()
  315.  * @param g - destination graphics context
  316.  */
  317. public void paint (Graphics g) {
  318.  
  319.        synchronized (fifo) {
  320.               fifo.paint (g);
  321.        }
  322. }
  323.  
  324. /**
  325.  * main() is the application entry point
  326.  * main() is unused when run as an applet
  327.  * create a window frame and add the applet inside
  328.  * @param args[] - command-line arguments
  329.  */
  330. public static void main (String args[]) {
  331.  
  332.        Frame f = new Frame ("Synchronized code example");
  333.  
  334.        SyncCode syncCode = new SyncCode ();
  335.        f.add ("Center", syncCode);
  336.        f.setSize (400, 200);
  337.        f.show ();
  338.        
  339.        syncCode.init ();
  340.        syncCode.start ();
  341. }
  342. }
  343.