153 lines
5.9 KiB
C#
153 lines
5.9 KiB
C#
/*-------------------------------------------------------------------------
|
|
// UNCLASSIFIED
|
|
/*-------------------------------------------------------------------------
|
|
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
|
|
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
|
|
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
|
|
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
|
|
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
|
|
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
|
|
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
|
|
COMPANY.
|
|
|
|
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
|
|
GOVERNMENT.
|
|
|
|
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
|
|
-------------------------------------------------------------------------*/
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
|
|
namespace ProgramLib
|
|
{
|
|
/// <summary>
|
|
/// Class that maps event array index to any event enumeration and wraps the WaitHandle.WaitAny() function
|
|
/// Use case:
|
|
/// When calling WaitHandle.WaitAny(EventArray), it only returns the index of the event in the array that is being signalled.
|
|
/// Refering to an index of the array to know which event it is is not ideal. We want to be able to refer to an enumeration instead
|
|
/// Usage:
|
|
/// In class that uses this class, must define a enumeration
|
|
/// public enum Events
|
|
/// {
|
|
/// EVENT1,
|
|
/// EVENT2,
|
|
/// EVENT3,
|
|
/// EVENTN
|
|
///
|
|
/// // DO NOT change the name
|
|
/// // This must be the last member in the enum
|
|
/// EVENT_TIMED_OUT
|
|
/// }
|
|
/// Dictionary<Events, EventWaitHandle> dict = new Dictionary<Events, EventWaitHandle>();
|
|
/// dict[Events.EVENT1] = new ManualResetEvent(false);
|
|
/// dict[Events.EVENT2] = new AutoResetEvent(false);
|
|
/// dict[Events.EVENT3] = new ManualResetEvent(false);
|
|
/// dict[Events.EVENTN] = new AutoResetEvent(false);
|
|
/// dict[Events.EVENT_TIMED_OUT] = null;
|
|
///
|
|
/// EventGroup<Events, EventWaitHandle> eventGroup = new EventGroup<Events, EventWaitHandle>(dict);
|
|
///
|
|
/// Events id = eventGroup.WaitAny([Optional_timeout]);
|
|
///
|
|
/// if (id == Events.EVENT_TIMED_OUT){} // only if timeout was specified
|
|
/// if (id == Events.EVENT1){}
|
|
///
|
|
/// </summary>
|
|
internal class EventGroup<T1, T2>
|
|
{
|
|
Dictionary<T1, T2> _eventDict = null;
|
|
T2[] _eventArray = null;
|
|
|
|
/// <summary>
|
|
/// Constructor
|
|
/// </summary>
|
|
private EventGroup()
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Constructor
|
|
/// The event enum passed in must be defined in the following format:
|
|
/// public enum Events
|
|
/// {
|
|
/// EVENT1,
|
|
/// EVENT2,
|
|
/// EVENT3,
|
|
/// EVENTN
|
|
///
|
|
/// // DO NOT change the name
|
|
/// // This must be the last member in the enum
|
|
/// EVENT_TIMED_OUT
|
|
/// }
|
|
/// </summary>
|
|
/// <param name="eventDict">A dictionary that contains event enum that is associated to an event object</param>
|
|
public EventGroup(Dictionary<T1, T2> eventDict)
|
|
{
|
|
if (eventDict == null)
|
|
throw new Exception($"{nameof(eventDict)} cannot be null");
|
|
|
|
if (!eventDict.First().Key.GetType().IsEnum)
|
|
{
|
|
throw new Exception($"{nameof(eventDict)}'s key must be an enumerated type");
|
|
}
|
|
|
|
// get the last element in the dictionary
|
|
var element = eventDict.ElementAt(eventDict.Count - 1);
|
|
|
|
// check if the name of the last enum member is what we expect
|
|
string actualNameOfLastEnumMember = ((Enum)Convert.ChangeType(element.Key, typeof(Enum))).ToString();
|
|
|
|
string expectedNameOfLastEnumMember = "EVENT_TIMED_OUT";
|
|
if (actualNameOfLastEnumMember != expectedNameOfLastEnumMember)
|
|
{
|
|
throw new Exception($"Enum {element.Key.GetType().Name} must have {expectedNameOfLastEnumMember} as its last member. {nameof(eventDict)} must have {expectedNameOfLastEnumMember} as the last key in the dictionary");
|
|
}
|
|
|
|
if (eventDict.First().Value.GetType().BaseType != typeof(EventWaitHandle))
|
|
{
|
|
throw new Exception($"{nameof(eventDict)}'s value must be ManualResetEvent or AutoResetEvent type");
|
|
}
|
|
_eventDict = eventDict;
|
|
|
|
_eventArray = new T2[_eventDict.Count - 1];
|
|
|
|
int index = 0;
|
|
foreach (KeyValuePair<T1, T2> entry in _eventDict)
|
|
{
|
|
if (index < _eventDict.Count - 1)
|
|
_eventArray[index++] = entry.Value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Return the enumerated event based on the index of the event in the event array that is being signalled
|
|
/// </summary>
|
|
/// <param name="timeoutMilliseconds">time out in milliseconds</param>
|
|
public T1 WaitAny(int? timeoutMilliseconds = null)
|
|
{
|
|
int index = 0;
|
|
T1 eventId = default;
|
|
|
|
if (timeoutMilliseconds == null)
|
|
index = WaitHandle.WaitAny((EventWaitHandle[])Convert.ChangeType(_eventArray, typeof(EventWaitHandle[])));
|
|
else
|
|
index = WaitHandle.WaitAny((EventWaitHandle[])Convert.ChangeType(_eventArray, typeof(EventWaitHandle[])), (int)timeoutMilliseconds);
|
|
|
|
if (index == WaitHandle.WaitTimeout)
|
|
{
|
|
var element = _eventDict.ElementAt(_eventDict.Count - 1);
|
|
eventId = element.Key;
|
|
}
|
|
else
|
|
{
|
|
var element = _eventDict.ElementAt(index);
|
|
eventId = element.Key;
|
|
}
|
|
|
|
return eventId;
|
|
}
|
|
}
|
|
}
|