/*------------------------------------------------------------------------- // 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 { /// /// 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 dict = new Dictionary(); /// 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 eventGroup = new EventGroup(dict); /// /// Events id = eventGroup.WaitAny([Optional_timeout]); /// /// if (id == Events.EVENT_TIMED_OUT){} // only if timeout was specified /// if (id == Events.EVENT1){} /// /// internal class EventGroup { Dictionary _eventDict = null; T2[] _eventArray = null; /// /// Constructor /// private EventGroup() { } /// /// 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 /// } /// /// A dictionary that contains event enum that is associated to an event object public EventGroup(Dictionary 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 entry in _eventDict) { if (index < _eventDict.Count - 1) _eventArray[index++] = entry.Value; } } /// /// Return the enumerated event based on the index of the event in the event array that is being signalled /// /// time out in milliseconds 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; } } }