/// <summary> /// Enqueue an event /// </summary> /// <param name="eventWrapper">an event wrapper</param> /// <param name="priority">the queue to enqueue to</param> private void Enqueue(EventWrapper <O, E> eventWrapper, byte priority) { if (priority > m_MaxPriority) { throw new ArgumentException(String.Format(CultureInfo.InvariantCulture, "Max priority is {0} and {1} was requested", m_MaxPriority, priority)); } if (priority < MIN_PRIORITY) { throw new ArgumentException(String.Format(CultureInfo.InvariantCulture, "Min priority is {0} and {1} was requested", MIN_PRIORITY, priority)); } // get the queue that corresponds to this priority Queue <EventWrapper <O, E> > eventQueue = m_EventQueues[priority]; // lock it lock (eventQueue) { // enqueue the event on it eventQueue.Enqueue(eventWrapper); } lock (m_PumpLock) { if (m_NumPendingEvents == 0 && m_PumpOn) { m_NumPendingEvents++; ScheduleHandleNextEvent(); return; } m_NumPendingEvents++; } }
/// <summary> /// Post and event /// </summary> /// <param name="callback"></param> /// <param name="anEvent"></param> /// <param name="priority"></param> /// <returns></returns> public Task <IState <O, E> > PostEvent(E anEvent, byte priority) { // create an AsyncResult for this event TaskCompletionSource <IState <O, E> > taskCompletionSource = new TaskCompletionSource <IState <O, E> >(anEvent); // wrap the event and the AsycResult together EventWrapper <O, E> eventWrapper = new EventWrapper <O, E>(anEvent, taskCompletionSource); // post the wrapper on the appropriate queue Enqueue(eventWrapper, priority); // return the AsyncResult return(taskCompletionSource.Task); }
private async Task HandleNextEvent() { //Logger.LogVerbose("Dequeue next event for {0}",m_Owner); // get the most eligible wrapped event EventWrapper <O, E> eventWrapper = Dequeue(); Debug.Assert(eventWrapper != null); IState <O, E> currentState = m_CurrentState; // retrieve the corresponding taskCompletionSource TaskCompletionSource <IState <O, E> > taskCompletionSource = eventWrapper.TaskCompletionSource; try { // call OnEvent of current state IState <O, E> nextState = await currentState.OnEvent(m_Owner, eventWrapper.Event, this); // if returned not null if (nextState != null) { // leave this state and enter the next await currentState.OnExit(m_Owner, nextState, this); m_CurrentState = nextState; await nextState.OnEntry(m_Owner, currentState, this); } try { taskCompletionSource.SetResult(m_CurrentState); } catch (InvalidOperationException) { // This is ok, there is a race condition between timeout and actual completion } } catch (Exception e) { // deliver the exception to the result try { taskCompletionSource.SetException(e); } catch (InvalidOperationException) { // This is ok, there is a race condition between timeout and actual completion } } finally { lock (m_PumpLock) { if (m_NumPendingEvents > 0) { m_NumPendingEvents--; if (m_NumPendingEvents > 0 && m_PumpOn) { ScheduleHandleNextEvent(); } } } } }