List Info

Thread: C-Sharp (C#) Group: Synchronized Queue




C-Sharp (C#) Group: Synchronized Queue
user name
2006-01-02 13:47:18
.NET provides the monitor class to synchronize access to a
resource.
(this is the class used when you use the lock() language
construct).
The Monitor makes sure that only one thread can access the
resource at
the same time. When the order in which the threads are
granted access
is not important, the monitor works great. However the
Monitor class
does _NOT_ guarantee FIFO behaviour.

Since for certain operations like in a production line, FIFO
behaviour
is an absolute requirement, I created a
SynchronizedQueue<T> class,
which does guarantee FIFO behaviour:

	/// <summary>
	/// This queue allows threads to queue for the use of a
resource
	/// or an operation. Unfortunately, Monitors do *not*
guarantee
	/// FIFO behaviour, so I've implemented this pretty queue.
	///
	/// Usage:
	///
	/// queue.Enter(this);
	///
	/// * perform operation *
	///
	/// queue.Release(this);
	/// </summary>
	/// <typeparam name="T"></typeparam>
	public class SynchronizedQueue<T> where T : class {
		Queue<T> _queue = new Queue<T>();

		/// <summary>
		/// Returns the element that currently can access the
resource
		/// </summary>
		public T CurrentElement {
			get {
				return _currentElement;
			}
		}
		T _currentElement;


		/// <summary>
		/// Enters the queue and waits until access to the
resource is
granted.
		/// </summary>
		/// <param name="item"></param>
		public void Enter(T item) {
			lock(_queue) {
				_queue.Enqueue(item);
			}

			while(_currentElement != item) {
				lock(_queue) {
					if(_currentElement == null) {
						_currentElement = _queue.Dequeue();
					}
				}
				Thread.Sleep(100);
			}
		}

		/// <summary>
		/// Releases the resource and exits the queue, thus
		/// allowing the next in line to access the resource.
		/// </summary>
		/// <param name="item"></param>
		public void Release(T item) {
			if(_currentElement != item) {
				throw new InvalidOperationException("Can't release
item '" + item +
", since it is not the current item.");
			}
			_currentElement = null;
		}

		/// <summary>
		/// Returns a string representation of this queue
		/// </summary>
		/// <returns></returns>
		public override string ToString() {
			return "SyncQueue with " + _queue.Count +
" elements. Current
element: " + CurrentElement;
		}
	}

C-Sharp (C#) Group: Re: Synchronized Queue
user name
2006-01-04 02:29:57
There are a few things that can be done to ensure that you
queue runs
in a FIFO fashion:
-the first would be to use a synchronisation object to for
the queue
-the second is the fact that you need a single thread to
operate on the
queue to process items in order
-below is a quick example of how this could be done (note it
may not
compile straight out as it was written in notepad)

public class SyncQueue<T> where T : class
{
    private object _syncQueue; //queue synchronisation
object
    priavate Queue<T> _queue; //the queue of all items
    private Thread _thread; //the thread that processes the
items

    //default constructor
    public SyncQueue()
    {
        this._syncQueue = new object();
        this._queue = new Queue<T>();
        this._thread = new Thread(new
ThreadStart(ProcessQueue));
    }

    //read access to the queue
    public Queue<T> Queue
    {
        get
        {
            lock (this._syncQueue)
            {
                //I have cloned so that it is read
                //only and the objects in the queue
                //(u dont have to make it ready only)
                reutrn new Queue<T>(this._queue);
            }
        }
    }

    //add an item to the queue
    public void Enqueue(T item)
    {
        lock (this._syncQueue)
        {
            this._queue.Enqueue(item);
        }

        //notify the processing thread to begin work again
        this._thread.Resume();
    }

    //remove an item from the queue
    public T Dequeue()
    {
        T item;
        lock (this._syncQueue)
        {
            item = this._queue.Dequeue();
        }
        return item;
    }


    //do some processing on the queue
    public void ProcessQueue()
    {
        //constant loop
        while (true)
        {
            //process when items are present
            if (this._queue.Count > 0)
            {
                T item = Dequeue();

                //***process the item here***
            }

            //make the thread wait until
            //something is added to the queue
            else
            {
               this._thread.Suspend();
            }
        }
    }
}

-To avoid a busy wait we suspend the processing thead when
there is
nothing to be processed
-I have also added readonly access to the queue by cloning
it; you
could allow access to modify the items by removing simply
returning the
queue object but this can be dangerous if the item is
removed from the
queue before it is operated on

[1-2]

about | contact  Other archives ( Real Estate discussion Medical topics )