//------------------------------------------------------------------------------ // // Copyright (c) Microsoft Corporation. All rights reserved. // //------------------------------------------------------------------------------ namespace System.Activities.Statements { using System; using System.Activities; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; using System.Runtime.Serialization; /// /// StateMachineEventManager is used to manage triggered events globally. /// [SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses", Justification = "This type is actually used in LINQ expression and FxCop didn't detect that.")] [DataContract] class StateMachineEventManager { // To avoid out of memory, set a fixed length of event queue. const int MaxQueueLength = 1 << 25; // queue is used to store triggered events Queue queue; // If a state is running, its condition evaluation bookmark will be added in to activityBookmarks. // If a state is completed, its bookmark will be removed. Collection activeBookmarks; /// /// Constructor to do initialization. /// public StateMachineEventManager() { this.queue = new Queue(); this.activeBookmarks = new Collection(); } /// /// Gets or sets the trigger index of current being processed event. /// [DataMember(EmitDefaultValue = false)] public TriggerCompletedEvent CurrentBeingProcessedEvent { get; set; } /// /// Gets or sets the CurrentConditionIndex denotes the index of condition is being evaluated. /// [DataMember(EmitDefaultValue = false)] public int CurrentConditionIndex { get; set; } /// /// Gets or sets a value indicating whether StateMachine is on the way of transition. /// [DataMember(EmitDefaultValue = false)] public bool OnTransition { get; set; } /// /// Gets the EventManager queue. /// public IEnumerable Queue { get { return this.queue; } } /// /// Gets a value indicating whether StateMachineManger is ready to process an event immediately. /// bool CanProcessEventImmediately { get { return this.CurrentBeingProcessedEvent == null && !this.OnTransition && this.queue.Count == 0; } } [DataMember(EmitDefaultValue = false, Name = "queue")] internal Queue SerializedQueue { get { return this.queue; } set { this.queue = value; } } [DataMember(EmitDefaultValue = false, Name = "activeBookmarks")] internal Collection SerializedActiveBookmarks { get { return this.activeBookmarks; } set { this.activeBookmarks = value; } } /// /// When StateMachine enters a state, condition evaluation bookmark of that state would be added to activeBookmarks collection. /// /// Bookmark reference. public void AddActiveBookmark(Bookmark bookmark) { this.activeBookmarks.Add(bookmark); } /// /// Gets next completed events queue. /// /// Top TriggerCompletedEvent item in the queue. public TriggerCompletedEvent GetNextCompletedEvent() { while (this.queue.Any()) { TriggerCompletedEvent completedEvent = this.queue.Dequeue(); if (this.activeBookmarks.Contains(completedEvent.Bookmark)) { this.CurrentBeingProcessedEvent = completedEvent; return completedEvent; } } return null; } /// /// This method is used to denote whether a given bookmark is referred by currently processed event. /// /// Bookmark reference. /// True is the bookmark references to the event being processed. public bool IsReferredByBeingProcessedEvent(Bookmark bookmark) { return this.CurrentBeingProcessedEvent != null && this.CurrentBeingProcessedEvent.Bookmark == bookmark; } /// /// Register a completed event and returns whether the event could be processed immediately. /// /// TriggerCompletedEvent reference. /// True if the Condition can be evaluated. public void RegisterCompletedEvent(TriggerCompletedEvent completedEvent, out bool canBeProcessedImmediately) { canBeProcessedImmediately = this.CanProcessEventImmediately; this.queue.Enqueue(completedEvent); return; } /// /// When StateMachine leaves a state, condition evaluation bookmark of that state would be removed from activeBookmarks collection. /// /// Bookmark reference. public void RemoveActiveBookmark(Bookmark bookmark) { this.activeBookmarks.Remove(bookmark); } } }