|
#region License
/* Copyright (c) 2008 Hamed Ebrahimmalek
*
* 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.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Threading;
using Operational.Interfaces;
using System.Diagnostics;
namespace EventHandler
{
#region Copyright Hamed Ebrahimmalek, 2008
// Hamed Ebrahimmalek
//
// Project : Proactor
// Module : Dispatcher
// File name : Dispatcher.cs
// Revision : 0.1
// Creation Date : 28-04-2008
// First Author : Hamed Ebrahimmalek
//
// Description :
//
#endregion
public sealed class Dispatcher
{
public enum Priority { VeryHigh = 0, High, Normal, Low, VeryLow, MAX };
/// <summary>
/// contains all the registered items
/// </summary>
private Hashtable _registry = new Hashtable();
/// <summary>
/// counts the created registry id
/// </summary>
private int _registeryID = 0;
/// <summary>
/// The disptachers thread
/// </summary>
private Thread _dispachThread = null;
/// <summary>
/// To hold and signal the running thread
/// </summary>
private Semaphore _autoResetEvent = new Semaphore( 0, int.MaxValue );
/// <summary>
/// The dispatchers instance
/// </summary>
static Dispatcher _instance = null;
/// <summary>
/// the dispatchers queue
/// </summary>
private PriorityQueue _queue = new PriorityQueue( (UInt32)Priority.MAX );
/// <summary>
/// This is used to lock the dispatchers instance
/// </summary>
private static readonly object _instanceLock = new object();
/// <summary>
/// Constructor, no default constructor allowed
/// This is a Singleton class.
/// </summary>
private Dispatcher()
{
}
/// <summary>
/// Initializes the dispatcher
/// </summary>
public void Initialize()
{
_dispachThread = new Thread(Dispatch);
}
/// <summary>
/// Starts the dispatcher
/// </summary>
public void Start()
{
// start the disptachers thread
_dispachThread.Start();
}
/// <summary>
/// Stops the dispatcher
/// </summary>
public void Stop()
{
// join the thread
_dispachThread.Join();
}
/// <summary>
/// Terminates the dispatcher
/// </summary>
public void Terminate( )
{
_autoResetEvent.Release();
}
/// <summary>
/// Dispatches the events to the dispatchable items
/// </summary>
private void Dispatch()
{
// thread must be running.
while (_dispachThread.ThreadState == System.Threading.ThreadState.Running)
{
// wait for signal
_autoResetEvent.WaitOne();
// the queue should have at least one queue item available
if( _queue.Count >= 1 )
{
QueueItem queueItem = null;
// We're going to dequeue an QueueItem from the dispatchers queue
lock (_queue)
{
// get a queue item
queueItem = _queue.Dequeue() as QueueItem;
// this must be valid!
Debug.Assert(queueItem != null);
// get the dispatchable item
IDispatchable dispItem = queueItem.DISP_ITEM;
// handle the event of the dispatchable item
dispItem.HandleEvent(queueItem.IEVENT);
}
}
}
}
/// <summary>
/// Registers the dispatchable items
/// </summary>
/// <param name="dispItem">the dispatchable items to register</param>
/// <returns>the registered dispatchable id</returns>
public int Register(IDispatchable dispItem)
{
// When registering a dispatchable item, this must be valid!
Debug.Assert(dispItem != null);
// one execution at a time
lock (_registry)
{
// insert the item to the registery
_registry.Add(_registeryID, dispItem);
// give the dispatchabe item its ID
dispItem.DISPATCHABLE_ID = _registeryID;
// count the id up
_registeryID++;
}
// return the original ID
return dispItem.DISPATCHABLE_ID;
}
/// <summary>
/// Enqueues the IEvent to the dispatchable item
/// </summary>
/// <param name="iDispID">the dispatchable id to enqueue the event to</param>
/// <param name="ievent">the event to dispatch</param>
public void Enqueue( int dispatchableID, IEvent ievent, Priority priority )
{
Debug.Assert(ievent != null);
IDispatchable dispItem = _registry[dispatchableID] as IDispatchable;
Debug.Assert(dispItem != null);
// create a new queue item
QueueItem queueItem = new QueueItem( dispItem, ievent );
// lock the enqueue, since the enqueue could take place from
// different threads.
lock (_queue)
{
_queue.Enqueue(queueItem, Convert.ToUInt32( priority ) );
}
// Tell the thread that we have inserted a new item
_autoResetEvent.Release();
}
/// <summary>
/// This method will return the Dispatchers instance
/// This is a Singleton pattern.
/// </summary>
public static Dispatcher GetInstance
{
get
{
lock (_instanceLock)
{
// if the instance exists, then return the
// already created disptacher
if (_instance == null)
{
// first time for the singleton
_instance = new Dispatcher();
}
return _instance;
}
}
}
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.