Jump to content



Photo

Problems with semaphores and buffers


  • Please log in to reply
2 replies to this topic

#1 Sarkhan Vol

Sarkhan Vol

    Awesome

  • Joined: 14-October 12

Posted 15 March 2013 - 16:53

I am currently trying to create a test road track with 2 cars one Red and one Blue which will run round the circuit from wait panel to wait panel once the buttons are clicked but no 2 cars can be in the same wait panel at the same time and each car must do a circuit of the track, but i'm currently having problems getting the cars to run the circuit, they just seem to run in each of the panels at the same time, how many semaphores and buffers do you need and how is this implemented and is there an easier way to work it out and there relationship to get them to circuit the track







using System;
using System.Windows.Forms;
using System.Threading;
using System.ComponentModel;
using System.Collections;
using System.Data;
using System.Drawing;

public class Form1 : Form
{
    private Container components = null;
    private ButtonPanelThread p1, p2;
    private Button btn1, btn3;
    private WaitPanelThread w1, w2;
    private WaitPanelThreadWest w4, w5;
    private WaitPanelThreadDown w3;
    private WaitPanelThreadDownUp w6;
    private Thread thread1, thread2, thread3, thread4, thread5, thread6, thread7, thread8;
    private Semaphore semaphore;
    private Buffer buffer;
    private Thread semThread;
    private Thread buffThread;
    private Panel pnl1, pnl2, wait1, wait2, wait3, wait4, wait5, wait6;


    public Form1()
    {
        InitializeComponent();

        semaphore = new Semaphore();
        buffer = new Buffer();

        p1 = new ButtonPanelThread(new Point(10, 40), 120, true, pnl1, Color.Blue, semaphore, buffer, btn1);      
        p2 = new ButtonPanelThread(new Point(10, 40), 120, true, pnl2, Color.Red, semaphore, buffer, btn3);

        w1 = new WaitPanelThread(new Point(10, 10), 120, true, wait1, Color.White, semaphore, buffer);
        w2 = new WaitPanelThread(new Point(10, 10), 120, true, wait2, Color.White, semaphore, buffer);
        w3 = new WaitPanelThreadDown(new Point(10, 10), 120, true, wait3, Color.White, semaphore, buffer);
        w4 = new WaitPanelThreadWest(new Point(200, 10), 120, true, wait4, Color.White, semaphore, buffer);
        w5 = new WaitPanelThreadWest(new Point(200, 10), 120, true, wait5, Color.White, semaphore, buffer);
        w6 = new WaitPanelThreadDownUp(new Point(10, 180), 120, true, wait6, Color.White, semaphore, buffer);


        semThread = new Thread(new ThreadStart(semaphore.Start));
        buffThread = new Thread(new ThreadStart(buffer.Start));

        thread1 = new Thread(new ThreadStart(p1.Start));        
        thread2 = new Thread(new ThreadStart(p2.Start));

        thread3 = new Thread(new ThreadStart(w1.Start));
        thread4 = new Thread(new ThreadStart(w2.Start));
        thread5 = new Thread(new ThreadStart(w3.Start));
        thread6 = new Thread(new ThreadStart(w4.Start));
        thread7 = new Thread(new ThreadStart(w5.Start));
        thread8 = new Thread(new ThreadStart(w6.Start));

        this.Closing += new CancelEventHandler(this.Form1_Closing);

        semThread.Start();
        buffThread.Start();

        thread1.Start();
        thread2.Start();
        thread3.Start();
        thread4.Start();
        thread5.Start();
        thread6.Start();
        thread7.Start();
        thread8.Start();
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            if (components != null)
                components.Dispose();
        }
        base.Dispose(disposing);
    }

    private void InitializeComponent()
    {
        this.pnl1 = new System.Windows.Forms.Panel();
        this.btn1 = new System.Windows.Forms.Button();
        this.pnl2 = new System.Windows.Forms.Panel();
        this.btn3 = new System.Windows.Forms.Button();
        this.wait1 = new System.Windows.Forms.Panel();
        this.wait2 = new System.Windows.Forms.Panel();
        this.wait3 = new System.Windows.Forms.Panel();
        this.wait4 = new System.Windows.Forms.Panel();
        this.wait5 = new System.Windows.Forms.Panel();
        this.wait6 = new System.Windows.Forms.Panel();
        this.pnl1.SuspendLayout();
        this.pnl2.SuspendLayout();
        this.SuspendLayout();

        this.pnl1.BackColor = System.Drawing.Color.White;
        this.pnl1.Controls.Add(this.btn1);
        this.pnl1.Location = new System.Drawing.Point(130, 4);
        this.pnl1.Name = "pnl1";
        this.pnl1.Size = new System.Drawing.Size(30, 178);
        this.pnl1.TabIndex = 0;

        this.btn1.BackColor = System.Drawing.Color.Pink;
        this.btn1.Location = new System.Drawing.Point(0, 0);
        this.btn1.Name = "btn1";
        this.btn1.Size = new System.Drawing.Size(30, 30);
        this.btn1.TabIndex = 0;
        this.btn1.UseVisualStyleBackColor = false;

        this.pnl2.BackColor = System.Drawing.Color.White;
        this.pnl2.Controls.Add(this.btn3);
        this.pnl2.Location = new System.Drawing.Point(390, 4);
        this.pnl2.Name = "pnl2";
        this.pnl2.Size = new System.Drawing.Size(30, 178);
        this.pnl2.TabIndex = 2;

        this.btn3.BackColor = System.Drawing.Color.Pink;
        this.btn3.Location = new System.Drawing.Point(0, 0);
        this.btn3.Name = "btn3";
        this.btn3.Size = new System.Drawing.Size(30, 30);
        this.btn3.TabIndex = 0;
        this.btn3.UseVisualStyleBackColor = false;

        this.wait1.BackColor = System.Drawing.Color.White;
        this.wait1.Location = new System.Drawing.Point(130, 182);
        this.wait1.Name = "wait1";
        this.wait1.Size = new System.Drawing.Size(260, 30);
        this.wait1.TabIndex = 1;

        this.wait2.BackColor = System.Drawing.Color.White;
        this.wait2.Location = new System.Drawing.Point(390, 182);
        this.wait2.Name = "wait2";
        this.wait2.Size = new System.Drawing.Size(260, 30);
        this.wait2.TabIndex = 3;

        this.wait3.BackColor = System.Drawing.Color.White;
        this.wait3.Location = new System.Drawing.Point(619, 212);
        this.wait3.Name = "wait3";
        this.wait3.Size = new System.Drawing.Size(31, 193);
        this.wait3.TabIndex = 2;

        this.wait4.BackColor = System.Drawing.Color.White;
        this.wait4.Location = new System.Drawing.Point(390, 405);
        this.wait4.Name = "wait4";
        this.wait4.Size = new System.Drawing.Size(260, 31);
        this.wait4.TabIndex = 4;

        this.wait5.BackColor = System.Drawing.Color.White;
        this.wait5.Location = new System.Drawing.Point(130, 405);
        this.wait5.Name = "wait5";
        this.wait5.Size = new System.Drawing.Size(260, 31);
        this.wait5.TabIndex = 5;

        this.wait6.BackColor = System.Drawing.Color.White;
        this.wait6.Location = new System.Drawing.Point(130, 212);
        this.wait6.Name = "wait6";
        this.wait6.Size = new System.Drawing.Size(30, 193);
        this.wait6.TabIndex = 6;

        this.BackColor = System.Drawing.Color.LightGray;
        this.ClientSize = new System.Drawing.Size(794, 609);
        this.Controls.Add(this.wait6);
        this.Controls.Add(this.wait5);
        this.Controls.Add(this.wait4);
        this.Controls.Add(this.wait3);
        this.Controls.Add(this.wait2);
        this.Controls.Add(this.wait1);
        this.Controls.Add(this.pnl1);
        this.Controls.Add(this.pnl2);
        this.Name = "Form1";
        this.Text = "Test Road Track";
        this.Closing += new System.ComponentModel.CancelEventHandler(this.Form1_Closing);
        this.pnl1.ResumeLayout(false);
        this.pnl2.ResumeLayout(false);
        this.ResumeLayout(false);

    }

    private void Form1_Closing(object sender, CancelEventArgs e)
    {       
        Environment.Exit(Environment.ExitCode);
    }

}

public class Buffer
{
    private Color planeColor;
    private bool empty = true;

    public void Read(ref Color planeColor)
    {
        lock (this)
        {            
            if (empty)
                Monitor.Wait(this);
            empty = true;
            planeColor = this.planeColor;
            Monitor.Pulse(this);
        }
    }

    public void Write(Color planeColor)
    {
        lock (this)
        {           
            if (!empty)
                Monitor.Wait(this);
            empty = false;
            this.planeColor = planeColor;
            Monitor.Pulse(this);
        }
    }

    public void Start()
    {
    }

}

public class Semaphore
{
    private int count = 0;

    public void Wait()
    {
        lock (this)
        {
            while (count == 0)
                Monitor.Wait(this);
            count = 0;
        }
    }

    public void Signal()
    {
        lock (this)
        {
            count = 1;
            Monitor.Pulse(this);
        }
    }

    public void Start()
    {
    }

}

public class ButtonPanelThread
{
    private Point origin;
    private int delay;
    private Panel panel;
    private bool westEast;
    private Color colour;
    private Point plane;
    private int xDelta;
    private int yDelta;
    private Semaphore semaphore;
    private Buffer buffer;
    private Button btn;
    private bool locked = true;

    public ButtonPanelThread(Point origin, int delay, bool westEast, Panel panel, Color colour, Semaphore semaphore, Buffer buffer, Button btn)
    {
        this.origin = origin;
        this.delay = delay;
        this.westEast = westEast;
        this.panel = panel;
        this.colour = colour;
        this.plane = origin;
        this.panel.Paint += new PaintEventHandler(this.panel_Paint);
        this.xDelta = westEast ? +0 : -0;
        this.yDelta = 6;
        this.semaphore = semaphore;
        this.buffer = buffer;
        this.btn = btn;
        this.btn.Click += new System.EventHandler(this.btn_Click);
    }

    private void btn_Click(object sender, System.EventArgs e)
    {
        locked = !locked;
        this.btn.BackColor = locked ? Color.Pink : Color.LightGreen;
        lock (this)
        {
            if (!locked)
                Monitor.Pulse(this);
        }
    }

    public void Start()
    {
        Color signal = Color.Red;
        Thread.Sleep(delay);

        for (int k = 1; k <= 6; k++)
        {
            this.zeroPlane();
            panel.Invalidate();
            lock (this)
            {
                while (locked)
                {
                    Monitor.Wait(this);
                }
            }
            for (int i = 1; i <= 20; i++)
            {
                this.movePlane(xDelta, yDelta);
                Thread.Sleep(delay);
                panel.Invalidate();
            }
            semaphore.Wait();
            buffer.Write(this.colour);
        }
        this.colour = Color.Gray;
        panel.Invalidate();
    }

    private void zeroPlane()
    {
        plane.X = origin.X;
        plane.Y = origin.Y;
    }

    private void movePlane(int xDelta, int yDelta)
    {
        plane.X += xDelta; plane.Y += yDelta;
    }

    private void panel_Paint(object sender, PaintEventArgs e)
    {
        Graphics g = e.Graphics;

        SolidBrush brush = new SolidBrush(colour);
        g.FillRectangle(brush, plane.X, plane.Y, 10, 10);

        brush.Dispose();   
        g.Dispose();        
    }
}

public class WaitPanelThread
{
    private Point origin;
    private int delay;
    private Panel panel;
    private bool westEast;
    private Color colour;
    private Point plane;
    private int xDelta;
    private int yDelta;
    private Semaphore semaphore;
    private Buffer buffer;

    public WaitPanelThread(Point origin, int delay, bool westEast, Panel panel, Color colour, Semaphore semaphore, Buffer buffer)
    {
        this.origin = origin;
        this.delay = delay;
        this.westEast = westEast;
        this.panel = panel;
        this.colour = colour;
        this.plane = origin;
        this.panel.Paint += new PaintEventHandler(this.panel_Paint);
        this.xDelta = westEast ? +10 : -10;
        this.yDelta = 0;
        this.semaphore = semaphore;
        this.buffer = buffer;
    }

    public void Start()
    {       
        this.colour = Color.White;
        for (int k = 1; k <= 12; k++)
        {
            semaphore.Signal();
            this.zeroPlane();

            buffer.Read(ref this.colour);

            for (int i = 1; i <= 20; i++)
            {
                panel.Invalidate();
                this.movePlane(xDelta, yDelta);
                Thread.Sleep(delay);

            }
            this.colour = Color.White;
            panel.Invalidate();
        }
        this.colour = Color.White;
        panel.Invalidate();
    }

    private void zeroPlane()
    {
        plane.X = origin.X;
        plane.Y = origin.Y;
    }

    private void movePlane(int xDelta, int yDelta)
    {
        plane.X += xDelta; plane.Y += yDelta;
    }

    private void panel_Paint(object sender, PaintEventArgs e)
    {
        Graphics g = e.Graphics;
        SolidBrush brush = new SolidBrush(colour);
        g.FillRectangle(brush, plane.X, plane.Y, 10, 10);
        brush.Dispose();   
        g.Dispose();     
    }
}

public class WaitPanelThreadWest
{
    private Point origin;
    private int delay;
    private Panel panel;
    private bool westEast;
    private Color colour;
    private Point plane;
    private int xDelta;
    private int yDelta;
    private Semaphore semaphore;
    private Buffer buffer;

    public WaitPanelThreadWest(Point origin, int delay, bool westEast, Panel panel, Color colour, Semaphore semaphore, Buffer buffer)
    {
        this.origin = origin;
        this.delay = delay;
        this.westEast = westEast;
        this.panel = panel;
        this.colour = colour;
        this.plane = origin;
        this.panel.Paint += new PaintEventHandler(this.panel_Paint);
        this.xDelta = westEast ? -10 : +10;
        this.yDelta = 0;
        this.semaphore = semaphore;
        this.buffer = buffer;
    }

    public void Start()
    {       
        this.colour = Color.White;
        for (int k = 1; k <= 12; k++)
        {
            semaphore.Signal();
            this.zeroPlane();

            buffer.Read(ref this.colour);

            for (int i = 1; i <= 20; i++)
            {
                panel.Invalidate();
                this.movePlane(xDelta, yDelta);
                Thread.Sleep(delay);

            }
            this.colour = Color.White;
            panel.Invalidate();
        }
        this.colour = Color.White;
        panel.Invalidate();
    }

    private void zeroPlane()
    {
        plane.X = origin.X;
        plane.Y = origin.Y;
    }

    private void movePlane(int xDelta, int yDelta)
    {
        plane.X += xDelta; plane.Y += yDelta;
    }

    private void panel_Paint(object sender, PaintEventArgs e)
    {
        Graphics g = e.Graphics;
        SolidBrush brush = new SolidBrush(colour);
        g.FillRectangle(brush, plane.X, plane.Y, 10, 10);
        brush.Dispose();    
        g.Dispose();        
    }
}

public class WaitPanelThreadDown
{
    private Point origin;
    private int delay;
    private Panel panel;
    private bool westEast;
    private Color colour;
    private Point plane;
    private int xDelta;
    private int yDelta;
    private Semaphore semaphore;
    private Buffer buffer;

    public WaitPanelThreadDown(Point origin, int delay, bool westEast, Panel panel, Color colour, Semaphore semaphore, Buffer buffer)
    {
        this.origin = origin;
        this.delay = delay;
        this.westEast = westEast;
        this.panel = panel;
        this.colour = colour;
        this.plane = origin;
        this.panel.Paint += new PaintEventHandler(this.panel_Paint);
        this.xDelta = westEast ? +0 : -0;
        this.yDelta = 10;
        this.semaphore = semaphore;
        this.buffer = buffer;
    }

    public void Start()
    {       
        this.colour = Color.White;
        for (int k = 1; k <= 12; k++)
        {
            semaphore.Signal();
            this.zeroPlane();

            buffer.Read(ref this.colour);

            for (int i = 1; i <= 20; i++)
            {
                panel.Invalidate();
                this.movePlane(xDelta, yDelta);
                Thread.Sleep(delay);

            }
            this.colour = Color.White;
            panel.Invalidate();
        }
        this.colour = Color.White;
        panel.Invalidate();
    }

    private void zeroPlane()
    {
        plane.X = origin.X;
        plane.Y = origin.Y;
    }

    private void movePlane(int xDelta, int yDelta)
    {
        plane.X += xDelta; plane.Y += yDelta;
    }

    private void panel_Paint(object sender, PaintEventArgs e)
    {
        Graphics g = e.Graphics;
        SolidBrush brush = new SolidBrush(colour);
        g.FillRectangle(brush, plane.X, plane.Y, 10, 10);
        brush.Dispose();     
        g.Dispose();       
    }
}

public class WaitPanelThreadDownUp
{
    private Point origin;
    private int delay;
    private Panel panel;
    private bool westEast;
    private Color colour;
    private Point plane;
    private int xDelta;
    private int yDelta;
    private Semaphore semaphore;
    private Buffer buffer;

    public WaitPanelThreadDownUp(Point origin, int delay, bool westEast, Panel panel, Color colour, Semaphore semaphore, Buffer buffer)
    {
        this.origin = origin;
        this.delay = delay;
        this.westEast = westEast;
        this.panel = panel;
        this.colour = colour;
        this.plane = origin;
        this.panel.Paint += new PaintEventHandler(this.panel_Paint);
        this.xDelta = westEast ? +0 : -0;
        this.yDelta = -10;
        this.semaphore = semaphore;
        this.buffer = buffer;
    }

    public void Start()
    {        
        this.colour = Color.White;
        for (int k = 1; k <= 12; k++)
        {
            semaphore.Signal();
            this.zeroPlane();

            buffer.Read(ref this.colour);

            for (int i = 1; i <= 20; i++)
            {
                panel.Invalidate();
                this.movePlane(xDelta, yDelta);
                Thread.Sleep(delay);

            }
            this.colour = Color.White;
            panel.Invalidate();
        }
        this.colour = Color.White;
        panel.Invalidate();
    }

    private void zeroPlane()
    {
        plane.X = origin.X;
        plane.Y = origin.Y;
    }

    private void movePlane(int xDelta, int yDelta)
    {
        plane.X += xDelta; plane.Y += yDelta;
    }

    private void panel_Paint(object sender, PaintEventArgs e)
    {
        Graphics g = e.Graphics;
        SolidBrush brush = new SolidBrush(colour);
        g.FillRectangle(brush, plane.X, plane.Y, 10, 10);
        brush.Dispose();    
        g.Dispose();         
    }
}

Attached Images

  • test1.jpg



#2 Andre S.

Andre S.

    Asik

  • Tech Issues Solved: 14
  • Joined: 26-October 05

Posted 22 March 2013 - 03:33

Why would run everything on its own thread? I suppose this is an academic exercise? Anyway it's difficult to tell what the different pieces of that code are supposed to achieve, perhaps if you can reformulate your question in a more succint manner you'll get a more useful reply.

#3 OP Sarkhan Vol

Sarkhan Vol

    Awesome

  • Joined: 14-October 12

Posted 22 March 2013 - 11:30

Why would run everything on its own thread? I suppose this is an academic exercise? Anyway it's difficult to tell what the different pieces of that code are supposed to achieve, perhaps if you can reformulate your question in a more succint manner you'll get a more useful reply.


heres a more simple example the car is meant to run the length of the track going from waitPanel to waitPanel using buffers and semaphores as its an example of thread concurrency, but instead the car runs in all the panels at the same time, this is because i'm using only one semaphore and one buffer, which explains why the car runs in all the panels at the same time, instead of just one car doing a lap of the track, the problem is how to make one car race round the track.

using System;
using System.Windows.Forms;
using System.Threading;
using System.ComponentModel;
using System.Collections;
using System.Data;
using System.Drawing;
public class Form1 : Form
{
	private Container components = null;
	private ButtonPanelThread p1;
	private Button btn1;
	private WaitPanelThread p2, p3, p4, p5;
	private Thread thread1, thread2, thread3, thread4, thread5;
	private Semaphore semaphore, semaphore1;
	private Buffer buffer, buffer1;
	private Thread semThread, semThread1;
	private Thread buffThread, buffThread1;
	private Panel pnl1, pnl2, pnl3, pnl4, pnl5;

	public Form1()
	{
		InitializeComponent();

		semaphore = new Semaphore();
		semaphore1 = new Semaphore();
		buffer = new Buffer();
		buffer1 = new Buffer();

		p1 = new ButtonPanelThread(new Point(40, 10),
							 30, true, pnl1,
							 Color.Blue,
							 semaphore,
							 buffer,
							 btn1);
		p2 = new WaitPanelThread(new Point(10, 10),
							 80, false, 2, pnl2,
							 Color.White,
							 semaphore,
							 buffer);
		p3 = new WaitPanelThread(new Point(10, 10),
							 77, false, 3, pnl3,
							 Color.White,
							 semaphore,
							 buffer);
		p4 = new WaitPanelThread(new Point(250, 10),
							 77, false, 4, pnl4,
							 Color.White,
							 semaphore,
							 buffer);
		p5 = new WaitPanelThread(new Point(10, 250),
							 77, false, 1, pnl5,
							 Color.White,
							 semaphore,
							 buffer);
		semThread = new Thread(new ThreadStart(semaphore.Start));
		semThread1 = new Thread(new ThreadStart(semaphore1.Start));
		buffThread = new Thread(new ThreadStart(buffer.Start));
		buffThread1 = new Thread(new ThreadStart(buffer1.Start));
		thread1 = new Thread(new ThreadStart(p1.Start));
		thread2 = new Thread(new ThreadStart(p2.Start));
		thread3 = new Thread(new ThreadStart(p3.Start));
		thread4 = new Thread(new ThreadStart(p4.Start));
		thread5 = new Thread(new ThreadStart(p5.Start));

		this.Closing += new CancelEventHandler(this.Form1_Closing);
		semThread.Start();
		semThread1.Start();
		buffThread.Start();
		buffThread1.Start();
		thread1.Start();
		thread2.Start();
		thread3.Start();
		thread4.Start();
		thread5.Start();
	}

	protected override void Dispose(bool disposing)
	{
		if (disposing)
		{
			if (components != null)
				components.Dispose();
		}
		base.Dispose(disposing);
	}
	private void InitializeComponent()
	{
		this.Text = "Circuit movements";
		this.Size = new System.Drawing.Size(900, 700);
		this.BackColor = Color.LightGray;
		this.pnl1 = new Panel();
		this.pnl1.Location = new Point(100, 100);
		this.pnl1.Size = new Size(260, 30);
		this.pnl1.BackColor = Color.White;
		this.btn1 = new Button();
		this.btn1.Size = new Size(30, 30);
		this.btn1.BackColor = Color.Pink;
		this.btn1.Location = new System.Drawing.Point(0, 0);

		this.pnl2 = new Panel();
		this.pnl2.Location = new Point(350, 100);
		this.pnl2.Size = new Size(260, 30);
		this.pnl2.BackColor = Color.White;
		this.pnl3 = new Panel();
		this.pnl3.Location = new Point(580, 100);
		this.pnl3.Size = new Size(30, 260);
		this.pnl3.BackColor = Color.White;
		this.pnl4 = new Panel();
		this.pnl4.Location = new Point(350, 360);
		this.pnl4.Size = new Size(260, 30);
		this.pnl4.BackColor = Color.White;
		this.pnl5 = new Panel();
		this.pnl5.Location = new Point(350, 100);
		this.pnl5.Size = new Size(30, 260);
		this.pnl5.BackColor = Color.White;
		this.Controls.Add(pnl1);
		this.Controls.Add(pnl2);
		this.Controls.Add(pnl3);
		this.Controls.Add(pnl4);
		this.Controls.Add(pnl5);
		this.pnl1.Controls.Add(btn1);
		// Wire Closing event.	
		this.Closing += new CancelEventHandler(this.Form1_Closing);
	}
	private void Form1_Closing(object sender, CancelEventArgs e)
	{
		// Environment is a System class.
		// Kill off all threads on exit.
		Environment.Exit(Environment.ExitCode);
	}

}// end class form1

public class Buffer
{
	private Color planeColor;
	private bool empty = true;
	public void Read(ref Color planeColor)
	{
		lock (this)
		{
			// Check whether the buffer is empty.
			if (empty)
				Monitor.Wait(this);
			empty = true;
			planeColor = this.planeColor;
			Monitor.Pulse(this);
		}
	}
	public void Write(Color planeColor)
	{
		lock (this)
		{
			// Check whether the buffer is full.
			if (!empty)
				Monitor.Wait(this);
			empty = false;
			this.planeColor = planeColor;
			Monitor.Pulse(this);
		}
	}
	public void Start()
	{
	}
}// end class Buffer
public class Semaphore
{
	private int count = 0;
	public void Wait()
	{
		lock (this)
		{
			while (count == 0)
				Monitor.Wait(this);
			count = 0;
		}
	}
	public void Signal()
	{
		lock (this)
		{
			count = 1;
			Monitor.Pulse(this);
		}
	}
	public void Start()
	{
	}
}// end class Semaphore
public class ButtonPanelThread
{
	private Point origin;
	private int delay;
	private Panel panel;
	private bool westEast;
	private Color colour;
	private Point plane;
	private int xDelta;
	private int yDelta;
	private Semaphore semaphore;
	private Buffer buffer;
	private Button btn;
	private bool locked = true;

	public ButtonPanelThread(Point origin,
							 int delay,
							 bool westEast,
							 Panel panel,
							 Color colour,
							 Semaphore semaphore,
							 Buffer buffer,
							 Button btn)
	{
		this.origin = origin;
		this.delay = delay;
		this.westEast = westEast;
		this.panel = panel;
		this.colour = colour;
		this.plane = origin;
		this.panel.Paint += new PaintEventHandler(this.panel_Paint);
		this.xDelta = westEast ? +10 : -10;
		this.yDelta = 0;
		this.semaphore = semaphore;
		this.buffer = buffer;
		this.btn = btn;
		this.btn.Click += new System.
							  EventHandler(this.btn_Click);

	}
	private void btn_Click(object sender,
						   System.EventArgs e)
	{
		locked = !locked;
		this.btn.BackColor = locked ? Color.Pink : Color.LightGreen;
		lock (this)
		{
			if (!locked)
				Monitor.Pulse(this);
		}
	}
	public void Start()
	{
		Color signal = Color.Red;
		Thread.Sleep(delay);

		for (int k = 1; k <= 30; k++)
		{
			this.zeroPlane();
			panel.Invalidate();
			lock (this)
			{
				while (locked)
				{
					Monitor.Wait(this);
				}
			}
			for (int i = 1; i <= 20; i++)
			{
				this.movePlane(xDelta, yDelta);
				Thread.Sleep(delay);
				panel.Invalidate();
			}
			semaphore.Wait();
			buffer.Write(this.colour);
		}
		this.colour = Color.Gray;
		panel.Invalidate();
	}
	private void zeroPlane()
	{
		plane.X = origin.X;
		plane.Y = origin.Y;
	}
	private void movePlane(int xDelta, int yDelta)
	{
		plane.X += xDelta; plane.Y += yDelta;
	}
	private void panel_Paint(object sender, PaintEventArgs e)
	{
		Graphics g = e.Graphics;
		SolidBrush brush = new SolidBrush(colour);
		g.FillRectangle(brush, plane.X, plane.Y, 10, 10);
		brush.Dispose();	//  Dispose graphics resources.
		g.Dispose();		//
	}
}// end class ButtonPanelThread
public class WaitPanelThread
{
	private Point origin;
	private int delay;
	private Panel panel;
	private bool westEast;
	private int dir;
	/*
	 * dir options:
	 * 1 - north;
	 * 2 - east;
	 * 3 - south;
	 * 4 - west.
	 */
	private Color colour;
	private Point plane;
	private int xDelta;
	private int yDelta;
	private Semaphore semaphore;
	private Buffer buffer;

	public WaitPanelThread(Point origin,
					   int delay,
					   bool westEast,
					   int dir,
					   Panel panel,
					   Color colour,
					   Semaphore sem,
					   Buffer buff)
	{
		this.origin = origin;
		this.delay = delay;
		this.westEast = westEast;
		this.dir = dir;
		this.panel = panel;
		this.colour = colour;
		this.plane = origin;
		this.panel.Paint += new PaintEventHandler(this.panel_Paint);
		switch (dir)
		{
			case 1:
				this.xDelta = 0;
				this.yDelta = -10;
				break;
			case 2:
				this.xDelta = +10;
				this.yDelta = 0;
				break;
			case 3:
				this.xDelta = 0;
				this.yDelta = +10;
				break;
			case 4:
				this.xDelta = -10;
				this.yDelta = 0;
				break;
		}
		this.semaphore = sem;
		this.buffer = buff;
	}
	public void Start()
	{
		this.colour = Color.White;
		for (int k = 1; k <= 40; k++)
		{
			semaphore.Signal();
			this.zeroPlane();
			buffer.Read(ref this.colour);
			for (int i = 1; i <= 20; i++)
			{
				panel.Invalidate();
				this.movePlane(xDelta, yDelta);
				Thread.Sleep(delay);
			}
			this.colour = Color.White;
			panel.Invalidate();

		}
		this.colour = Color.Gray;
		panel.Invalidate();
	}
	private void zeroPlane()
	{
		plane.X = origin.X;
		plane.Y = origin.Y;
	}
	private void movePlane(int xDelta, int yDelta)
	{
		plane.X += xDelta; plane.Y += yDelta;
	}
	private void panel_Paint(object sender, PaintEventArgs e)
	{
		Graphics g = e.Graphics;
		SolidBrush brush = new SolidBrush(colour);
		if (dir == 2 || dir == 4)
		{
			g.FillRectangle(brush, plane.X, plane.Y, 10, 10);
		}
		if (dir == 1 || dir == 3)
		{
			g.FillRectangle(brush, plane.X, plane.Y, 10, 10);
		}
		brush.Dispose();	//  Dispose graphics resources.
		g.Dispose();		//
	}
}// end class WaitPanelThread
public class Driver
{
	public static void Main()//
	{
		Application.Run(new Form1());
	}
}// end class TheOne