Initial check-in
This commit is contained in:
154
Source/Program/Common/Misc/EventGroup.cs
Normal file
154
Source/Program/Common/Misc/EventGroup.cs
Normal file
@@ -0,0 +1,154 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
// 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.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user