diff --git a/Nuclex.Support (x86).csproj b/Nuclex.Support (x86).csproj index 4a0ae00..3e30fc9 100644 --- a/Nuclex.Support (x86).csproj +++ b/Nuclex.Support (x86).csproj @@ -151,9 +151,9 @@ - - - QueueOperation.cs + + + OperationQueue.cs @@ -178,9 +178,9 @@ ProgressTracker.cs - - - SetProgression.cs + + + WaitableGroup.cs diff --git a/Source/Collections/ObservableCollection.cs b/Source/Collections/ObservableCollection.cs index 2e9e347..c33a956 100644 --- a/Source/Collections/ObservableCollection.cs +++ b/Source/Collections/ObservableCollection.cs @@ -57,7 +57,7 @@ namespace Nuclex.Support.Collections { } /// - /// Inserts an element into the ProgressionCollection at the specified index + /// Inserts an element into the ObservableCollection at the specified index /// /// /// The object to insert. The value can be null for reference types. @@ -70,7 +70,7 @@ namespace Nuclex.Support.Collections { } /// - /// Removes the element at the specified index of the ProgressionCollection + /// Removes the element at the specified index of the ObservableCollection /// /// The zero-based index of the element to remove protected override void RemoveItem(int index) { diff --git a/Source/Scheduling/QueueOperation.Test.cs b/Source/Scheduling/OperationQueue.Test.cs similarity index 86% rename from Source/Scheduling/QueueOperation.Test.cs rename to Source/Scheduling/OperationQueue.Test.cs index fdf2d4e..d3623f1 100644 --- a/Source/Scheduling/QueueOperation.Test.cs +++ b/Source/Scheduling/OperationQueue.Test.cs @@ -33,11 +33,11 @@ namespace Nuclex.Support.Scheduling { /// Unit Test for the queue operation class [TestFixture] - public class QueueOperationTest { + public class OperationQueueTest { #region interface IQueueOperationSubscriber - /// Interface used to test the set progression. + /// Interface used to test the set waitable. public interface IQueueOperationSubscriber { /// Called when the queue operations's progress changes @@ -95,7 +95,7 @@ namespace Nuclex.Support.Scheduling { #region class TestOperation - /// Progression used for testing in this unit test + /// Operation used for testing in this unit test private class TestOperation : Operation, IProgressReporter { /// will be triggered to report when progress has been achieved @@ -116,9 +116,9 @@ namespace Nuclex.Support.Scheduling { OnAsyncEnded(); } - /// Changes the testing progression's indicated progress + /// Changes the testing operation's indicated progress /// - /// New progress to be reported by the testing progression + /// New progress to be reported by the testing operation /// public void ChangeProgress(float progress) { OnAsyncProgressChanged(progress); @@ -136,7 +136,7 @@ namespace Nuclex.Support.Scheduling { /// Fires the progress update event /// Progress to report (ranging from 0.0 to 1.0) /// - /// Informs the observers of this progression about the achieved progress. + /// Informs the observers of this operation about the achieved progress. /// protected virtual void OnAsyncProgressChanged(float progress) { OnAsyncProgressChanged(new ProgressReportEventArgs(progress)); @@ -145,10 +145,10 @@ namespace Nuclex.Support.Scheduling { /// Fires the progress update event /// Progress to report (ranging from 0.0 to 1.0) /// - /// Informs the observers of this progression about the achieved progress. - /// Allows for classes derived from the Progression class to easily provide + /// Informs the observers of this operation about the achieved progress. + /// Allows for classes derived from the Operation class to easily provide /// a custom event arguments class that has been derived from the - /// Progression's ProgressUpdateEventArgs class. + /// operation's ProgressUpdateEventArgs class. /// protected virtual void OnAsyncProgressChanged(ProgressReportEventArgs eventArguments) { EventHandler copy = AsyncProgressChanged; @@ -175,8 +175,8 @@ namespace Nuclex.Support.Scheduling { TestOperation operation1 = new TestOperation(); TestOperation operation2 = new TestOperation(); - QueueOperation testQueueOperation = - new QueueOperation( + OperationQueue testQueueOperation = + new OperationQueue( new TestOperation[] { operation1, operation2 } ); @@ -188,7 +188,7 @@ namespace Nuclex.Support.Scheduling { Method("ProgressChanged"). With( new Matcher[] { - new NMock2.Matchers.TypeMatcher(typeof(QueueOperation)), + new NMock2.Matchers.TypeMatcher(typeof(OperationQueue)), new ProgressUpdateEventArgsMatcher(new ProgressReportEventArgs(0.25f)) } ); @@ -199,7 +199,7 @@ namespace Nuclex.Support.Scheduling { Method("ProgressChanged"). With( new Matcher[] { - new NMock2.Matchers.TypeMatcher(typeof(QueueOperation)), + new NMock2.Matchers.TypeMatcher(typeof(OperationQueue)), new ProgressUpdateEventArgsMatcher(new ProgressReportEventArgs(0.5f)) } ); diff --git a/Source/Scheduling/QueueOperation.cs b/Source/Scheduling/OperationQueue.cs similarity index 88% rename from Source/Scheduling/QueueOperation.cs rename to Source/Scheduling/OperationQueue.cs index 79edaed..bfd441c 100644 --- a/Source/Scheduling/QueueOperation.cs +++ b/Source/Scheduling/OperationQueue.cs @@ -29,7 +29,7 @@ namespace Nuclex.Support.Scheduling { /// /// Type of the child operations the QueueOperation will contain /// - public class QueueOperation : Operation, IProgressReporter + public class OperationQueue : Operation, IProgressReporter where OperationType : Operation { /// will be triggered to report when progress has been achieved @@ -40,24 +40,24 @@ namespace Nuclex.Support.Scheduling { /// /// All child operations will have a default weight of 1.0 /// - public QueueOperation(IEnumerable childs) : this() { + public OperationQueue(IEnumerable childs) : this() { - // Construct a WeightedProgression with the default weight for each - // progression and wrap it in an ObservedProgression + // Construct a WeightedWaitable with the default weight for each + // waitable and wrap it in an ObservedWaitable foreach(OperationType operation in childs) this.children.Add(new WeightedWaitable(operation)); - // Since all progressions have a weight of 1.0, the total weight is - // equal to the number of progressions in our list + // Since all waitables have a weight of 1.0, the total weight is + // equal to the number of waitables in our list this.totalWeight = (float)this.children.Count; } /// Initializes a new queue operation with custom weights /// Child operations to execute in this operation - public QueueOperation(IEnumerable> childs) : this() { + public OperationQueue(IEnumerable> childs) : this() { - // Construct an ObservedProgression around each of the WeightedProgressions + // Construct an ObservedWaitablen around each of the WeightedWaitables foreach(WeightedWaitable operation in childs) { this.children.Add(operation); @@ -68,7 +68,7 @@ namespace Nuclex.Support.Scheduling { } /// Initializes a new queue operation - private QueueOperation() { + private OperationQueue() { this.asyncOperationEndedDelegate = new EventHandler(asyncOperationEnded); this.asyncOperationProgressChangedDelegate = new EventHandler( asyncOperationProgressChanged @@ -99,7 +99,7 @@ namespace Nuclex.Support.Scheduling { /// Fires the progress update event /// Progress to report (ranging from 0.0 to 1.0) /// - /// Informs the observers of this progression about the achieved progress. + /// Informs the observers of this waitable about the achieved progress. /// protected virtual void OnAsyncProgressChanged(float progress) { OnAsyncProgressChanged(new ProgressReportEventArgs(progress)); @@ -108,10 +108,10 @@ namespace Nuclex.Support.Scheduling { /// Fires the progress update event /// Progress to report (ranging from 0.0 to 1.0) /// - /// Informs the observers of this progression about the achieved progress. - /// Allows for classes derived from the Progression class to easily provide + /// Informs the observers of this waitable about the achieved progress. + /// Allows for classes derived from the Waitable class to easily provide /// a custom event arguments class that has been derived from the - /// Progression's ProgressUpdateEventArgs class. + /// waitable's ProgressUpdateEventArgs class. /// protected virtual void OnAsyncProgressChanged(ProgressReportEventArgs eventArguments) { EventHandler copy = AsyncProgressChanged; diff --git a/Source/Tracking/Internal/ObservedWeightedWaitable.cs b/Source/Tracking/Internal/ObservedWeightedWaitable.cs index 0020b4a..1fa6c76 100644 --- a/Source/Tracking/Internal/ObservedWeightedWaitable.cs +++ b/Source/Tracking/Internal/ObservedWeightedWaitable.cs @@ -23,33 +23,33 @@ using System.Collections.Generic; namespace Nuclex.Support.Tracking { - /// Progression being observed by another class - /// - /// Type of the progression that is being observed + /// Waitable being observed by another object + /// + /// Type of the waitable that is being observed /// - internal class ObservedWeightedWaitable : IDisposable - where ProgressionType : Waitable { + internal class ObservedWeightedWaitable : IDisposable + where WaitableType : Waitable { /// Delegate for reporting progress updates public delegate void ReportDelegate(); - /// Initializes a new observed progression - /// Weighted progression being observed + /// Initializes a new observed waitable + /// Weighted waitable being observed /// - /// Callback to invoke when the progression's progress changes + /// Callback to invoke when the waitable's progress changes /// /// - /// Callback to invoke when the progression has ended + /// Callback to invoke when the waitable has ended /// internal ObservedWeightedWaitable( - WeightedWaitable weightedProgression, + WeightedWaitable weightedWaitable, ReportDelegate progressUpdateCallback, ReportDelegate endedCallback ) { - this.weightedProgression = weightedProgression; + this.weightedWaitable = weightedWaitable; - // See if this progression has already ended (initial check for performance) - if(weightedProgression.Waitable.Ended) { + // See if this waitable has already ended (initial check for performance) + if(weightedWaitable.Waitable.Ended) { this.progress = 1.0f; @@ -58,18 +58,18 @@ namespace Nuclex.Support.Tracking { this.endedCallback = endedCallback; this.progressUpdateCallback = progressUpdateCallback; - this.weightedProgression.Waitable.AsyncEnded += + this.weightedWaitable.Waitable.AsyncEnded += new EventHandler(asyncEnded); - // Check whether this progression might have ended before we were able to + // Check whether this waitable might have ended before we were able to // attach ourselfes to its event. If so, don't bother registering to the // other event and (important) set our progress to 1.0 because, since we // might not have gotten the 'Ended' event, it might otherwise stay at 0.0 - // even though the progression is in the 'Ended' state. - if(weightedProgression.Waitable.Ended) { + // even though the waitable is in the 'Ended' state. + if(weightedWaitable.Waitable.Ended) { this.progress = 1.0f; } else { - this.progressReporter = this.weightedProgression.Waitable as IProgressReporter; + this.progressReporter = this.weightedWaitable.Waitable as IProgressReporter; if(this.progressReporter != null) { this.asyncProgressChangedEventHandler = new EventHandler( @@ -89,18 +89,18 @@ namespace Nuclex.Support.Tracking { asyncDisconnectEvents(); } - /// Weighted progression being observed - public WeightedWaitable WeightedWaitable { - get { return this.weightedProgression; } + /// Weighted waitable being observed + public WeightedWaitable WeightedWaitable { + get { return this.weightedWaitable; } } - /// Amount of progress this progression has achieved so far + /// Amount of progress this waitable has achieved so far public float Progress { get { return this.progress; } } - /// Called when the observed progression has ended - /// Progression that has ended + /// Called when the observed waitable has ended + /// Waitable that has ended /// Not used private void asyncEnded(object sender, EventArgs e) { ReportDelegate endedCallback = this.endedCallback; @@ -109,11 +109,11 @@ namespace Nuclex.Support.Tracking { asyncDisconnectEvents(); // We don't need those anymore! // If the progress hasn't reached 1.0 yet, make a fake report so that even - // when a progression doesn't report any progress at all, the set or queue - // owning us will have a percentage of progressions completed. + // when a waitable doesn't report any progress at all, the set or queue + // owning us will have a percentage of waitables completed. // // There is the possibility of a race condition here, as a final progress - // report could have been generated by a thread running the progression + // report could have been generated by a thread running the waitable // that was preempted by this thread. This would cause the progress to // jump to 1.0 and then back to whatever the waiting thread will report. if(this.progress != 1.0f) { @@ -124,15 +124,15 @@ namespace Nuclex.Support.Tracking { endedCallback(); } - /// Called when the progress of the observed progression changes - /// Progression whose progress has changed + /// Called when the progress of the observed waitable changes + /// Waitable whose progress has changed /// Contains the updated progress private void asyncProgressChanged(object sender, ProgressReportEventArgs e) { this.progress = e.Progress; this.progressUpdateCallback(); } - /// Unsubscribes from all events of the observed progression + /// Unsubscribes from all events of the observed waitable private void asyncDisconnectEvents() { // Make use of the double check locking idiom to avoid the costly lock when @@ -143,8 +143,7 @@ namespace Nuclex.Support.Tracking { // is no risk of deadlock involved, so we don't need a fancy syncRoot! lock(this) { if(this.endedCallback != null) { - this.weightedProgression.Waitable.AsyncEnded -= - new EventHandler(asyncEnded); + this.weightedWaitable.Waitable.AsyncEnded -= new EventHandler(asyncEnded); if(this.progressReporter != null) { this.progressReporter.AsyncProgressChanged -= @@ -163,13 +162,13 @@ namespace Nuclex.Support.Tracking { } private EventHandler asyncProgressChangedEventHandler; - /// The observed progression's progress reporting interface + /// The observed waitable's progress reporting interface private IProgressReporter progressReporter; - /// The weighted progression that is being observed - private WeightedWaitable weightedProgression; + /// The weighted wable that is being observed + private WeightedWaitable weightedWaitable; /// Callback to invoke when the progress updates private volatile ReportDelegate progressUpdateCallback; - /// Callback to invoke when the progression ends + /// Callback to invoke when the waitable ends private volatile ReportDelegate endedCallback; /// Progress achieved so far private volatile float progress; diff --git a/Source/Tracking/Internal/WeightedWaitableWrapperCollection.cs b/Source/Tracking/Internal/WeightedWaitableWrapperCollection.cs index b01c183..8ffb4ef 100644 --- a/Source/Tracking/Internal/WeightedWaitableWrapperCollection.cs +++ b/Source/Tracking/Internal/WeightedWaitableWrapperCollection.cs @@ -27,36 +27,36 @@ using Nuclex.Support.Collections; namespace Nuclex.Support.Tracking { - /// Collection of progressions with a weighting value - /// Type of progressions to manage + /// Collection of waitables with a weighting value + /// Type of waitables to manage /// /// /// This collection is exposed as a read-only collection to the user that - /// stores WeightedProgressions. Internally, it merely wraps a collection of - /// an internal type used to keep track of the individual progression's - /// progress in the SetProgression and QueueOperation classes. + /// stores WeightedWaitables. Internally, it merely wraps a collection of + /// an internal type used to keep track of the individual waitable's + /// progress in the WaitableSet and OperationQueue classes. /// /// - /// It is read-only because the design requires a progression to only ever - /// finish once. If it was possible eg. to add items after a SetProgression + /// It is read-only because the design requires a waitable to only ever + /// finish once. If it was possible eg. to add items after a WaitableSet /// had signalled itself as being finished, it would be moved into an - /// unfinished state again. Also, an empty SetProgression is, by definition, + /// unfinished state again. Also, an empty WaitableSet is, by definition, /// finished (simply because there is no work to do) - unless the contents - /// of set are passed to the SetProgression's constructor and never modified + /// of set are passed to the WaitableSet's constructor and never modified /// at all, the design would be violated as soon as ab instance of the - /// SetProgression or QueueOperation classes was created. + /// WaitableSet or OperationQueue classes was created. /// /// - internal class WeightedProgressionWrapperCollection : + internal class WeightedWaitableWrapperCollection : TransformingReadOnlyCollection< - ObservedWeightedWaitable, WeightedWaitable + ObservedWeightedWaitable, WeightedWaitable > - where ProgressionType : Waitable { + where WaitableType : Waitable { - /// Initializes a new weighted progression collection wrapper - /// Items to be exposed as weighted progressions - internal WeightedProgressionWrapperCollection( - IList> items + /// Initializes a new weighted waitable collection wrapper + /// Items to be exposed as weighted waitables + internal WeightedWaitableWrapperCollection( + IList> items ) : base(items) { } @@ -69,8 +69,8 @@ namespace Nuclex.Support.Tracking { /// be called frequently, because the TransformingReadOnlyCollection does /// not cache otherwise store the transformed items. /// - protected override WeightedWaitable Transform( - ObservedWeightedWaitable item + protected override WeightedWaitable Transform( + ObservedWeightedWaitable item ) { return item.WeightedWaitable; } diff --git a/Source/Tracking/ProgressTracker.Test.cs b/Source/Tracking/ProgressTracker.Test.cs index 3dc80fc..248b125 100644 --- a/Source/Tracking/ProgressTracker.Test.cs +++ b/Source/Tracking/ProgressTracker.Test.cs @@ -29,28 +29,28 @@ using NMock2; namespace Nuclex.Support.Tracking { - /// Unit Test for the progression tracker class + /// Unit Test for the progress tracker class [TestFixture] - public class ProgressionTrackerTest { + public class ProgressTrackerTest { - #region interface IProgressionTrackerSubscriber + #region interface IProgressTrackerSubscriber - /// Interface used to test the progression tracker. - public interface IProgressionTrackerSubscriber { + /// Interface used to test the progress tracker + public interface IProgressTrackerSubscriber { - /// Called when the progression tracker's progress changes - /// Progression tracker whose progress has changed + /// Called when the tracked progress changes + /// Progress tracker whose progress has changed /// Contains the new progress achieved void ProgressChanged(object sender, ProgressReportEventArgs e); - /// Called when the progression tracker's idle state changes - /// Progression tracker whose idle state has changed + /// Called when the progress tracker's idle state changes + /// Progress tracker whose idle state has changed /// Contains the new idle state of the tracker void IdleStateChanged(object sender, IdleStateEventArgs e); } - #endregion // interface IProgressionTrackerSubscriber + #endregion // interface IProgressTrackerSubscriber #region class ProgressUpdateEventArgsMatcher @@ -91,23 +91,21 @@ namespace Nuclex.Support.Tracking { #endregion // class ProgressUpdateEventArgsMatcher - #region class TestProgression + #region class TestWaitable - /// Progression used for testing in this unit test - private class TestProgression : Waitable, IProgressReporter { + /// Waitable used for testing in this unit test + private class TestWaitable : Waitable, IProgressReporter { /// will be triggered to report when progress has been achieved public event EventHandler AsyncProgressChanged; - /// Changes the testing progression's indicated progress - /// - /// New progress to be reported by the testing progression - /// + /// Changes the testing waitable's indicated progress + /// New progress to be reported by the testing waitable public void ChangeProgress(float progress) { OnAsyncProgressChanged(progress); } - /// Transitions the progression into the ended state + /// Transitions the waitable into the ended state public void End() { OnAsyncEnded(); } @@ -115,7 +113,7 @@ namespace Nuclex.Support.Tracking { /// Fires the progress update event /// Progress to report (ranging from 0.0 to 1.0) /// - /// Informs the observers of this progression about the achieved progress. + /// Informs the observers of this waitable about the achieved progress. /// protected virtual void OnAsyncProgressChanged(float progress) { OnAsyncProgressChanged(new ProgressReportEventArgs(progress)); @@ -124,10 +122,10 @@ namespace Nuclex.Support.Tracking { /// Fires the progress update event /// Progress to report (ranging from 0.0 to 1.0) /// - /// Informs the observers of this progression about the achieved progress. - /// Allows for classes derived from the Progression class to easily provide + /// Informs the observers of this waitable about the achieved progress. + /// Allows for classes derived from the Waitable class to easily provide /// a custom event arguments class that has been derived from the - /// Progression's ProgressUpdateEventArgs class. + /// waitable's ProgressUpdateEventArgs class. /// protected virtual void OnAsyncProgressChanged(ProgressReportEventArgs eventArguments) { EventHandler copy = AsyncProgressChanged; @@ -137,7 +135,7 @@ namespace Nuclex.Support.Tracking { } - #endregion // class TestProgression + #endregion // class TestWiatable /// Initialization routine executed before each test is run [SetUp] @@ -150,7 +148,7 @@ namespace Nuclex.Support.Tracking { public void TestSummedProgress() { ProgressTracker tracker = new ProgressTracker(); - IProgressionTrackerSubscriber mockedSubscriber = mockSubscriber(tracker); + IProgressTrackerSubscriber mockedSubscriber = mockSubscriber(tracker); Expect.Once.On(mockedSubscriber). Method("IdleStateChanged"). @@ -165,9 +163,9 @@ namespace Nuclex.Support.Tracking { } ); - TestProgression test1 = new TestProgression(); + TestWaitable test1 = new TestWaitable(); tracker.Track(test1); - TestProgression test2 = new TestProgression(); + TestWaitable test2 = new TestWaitable(); tracker.Track(test2); Expect.Once.On(mockedSubscriber). @@ -185,18 +183,18 @@ namespace Nuclex.Support.Tracking { } /// - /// Validates that the tracker only removes progressions when the whole + /// Validates that the tracker only removes waitables when the whole /// tracking list has reached the 'ended' state. /// /// - /// If the tracker would remove ended progressions right when they finished, + /// If the tracker would remove ended waitables right when they finished, /// the total progress would jump back each time. This is unwanted, of course. /// [Test] public void TestDelayedRemoval() { ProgressTracker tracker = new ProgressTracker(); - IProgressionTrackerSubscriber mockedSubscriber = mockSubscriber(tracker); + IProgressTrackerSubscriber mockedSubscriber = mockSubscriber(tracker); Expect.Once.On(mockedSubscriber). Method("IdleStateChanged"). @@ -211,9 +209,9 @@ namespace Nuclex.Support.Tracking { } ); - TestProgression test1 = new TestProgression(); + TestWaitable test1 = new TestWaitable(); tracker.Track(test1); - TestProgression test2 = new TestProgression(); + TestWaitable test2 = new TestWaitable(); tracker.Track(test2); Expect.Once.On(mockedSubscriber). @@ -236,8 +234,8 @@ namespace Nuclex.Support.Tracking { } ); - // Total progress should be 0.75 after this call (one progression at 1.0, - // the other one at 0.5). If the second progression would be removed, + // Total progress should be 0.75 after this call (one waitable at 1.0, + // the other one at 0.5). If the second waitable would be removed, // the progress would jump to 0.5 instead. test2.End(); @@ -260,14 +258,14 @@ namespace Nuclex.Support.Tracking { } /// - /// Validates that the tracker behaves correctly if it is fed with progressions + /// Validates that the tracker behaves correctly if it is fed with waitables /// that have already ended. /// [Test] - public void TestSoleEndedProgression() { + public void TestSoleEndedWaitable() { ProgressTracker tracker = new ProgressTracker(); - IProgressionTrackerSubscriber mockedSubscriber = mockSubscriber(tracker); + IProgressTrackerSubscriber mockedSubscriber = mockSubscriber(tracker); tracker.Track(Waitable.EndedDummy); @@ -275,14 +273,14 @@ namespace Nuclex.Support.Tracking { } /// - /// Validates that the tracker behaves correctly if it is fed with progressions - /// that have already ended in addition to progressions that are actively executing. + /// Validates that the tracker behaves correctly if it is fed with waitables + /// that have already ended in addition to waitables that are actively executing. /// [Test] - public void TestEndedProgression() { + public void TestEndedWaitable() { ProgressTracker tracker = new ProgressTracker(); - IProgressionTrackerSubscriber mockedSubscriber = mockSubscriber(tracker); + IProgressTrackerSubscriber mockedSubscriber = mockSubscriber(tracker); Expect.Once.On(mockedSubscriber). Method("IdleStateChanged"). @@ -297,7 +295,7 @@ namespace Nuclex.Support.Tracking { } ); - TestProgression test1 = new TestProgression(); + TestWaitable test1 = new TestWaitable(); tracker.Track(test1); Expect.Once.On(mockedSubscriber). @@ -337,7 +335,7 @@ namespace Nuclex.Support.Tracking { public void TestProvokedDeadlock() { ProgressTracker tracker = new ProgressTracker(); - TestProgression test1 = new TestProgression(); + TestWaitable test1 = new TestWaitable(); tracker.Track(test1); tracker.AsyncIdleStateChanged += @@ -351,9 +349,9 @@ namespace Nuclex.Support.Tracking { /// Mocks a subscriber for the events of a tracker /// Tracker to mock an event subscriber for /// The mocked event subscriber - private IProgressionTrackerSubscriber mockSubscriber(ProgressTracker tracker) { - IProgressionTrackerSubscriber mockedSubscriber = - this.mockery.NewMock(); + private IProgressTrackerSubscriber mockSubscriber(ProgressTracker tracker) { + IProgressTrackerSubscriber mockedSubscriber = + this.mockery.NewMock(); tracker.AsyncIdleStateChanged += new EventHandler(mockedSubscriber.IdleStateChanged); diff --git a/Source/Tracking/Request.cs b/Source/Tracking/Request.cs index 341bf9f..a320148 100644 --- a/Source/Tracking/Request.cs +++ b/Source/Tracking/Request.cs @@ -23,18 +23,18 @@ using System.Collections.Generic; namespace Nuclex.Support.Tracking { - /// Extended type of progression that is able to fail + /// Asynchronous request running in the background /// /// /// If the background process fails, the exception that caused it to fail is - /// communicated to all parties waiting on the progression through the - /// Exception property. Implementers should place their code in try..catch - /// blocks and call SetException() to temporarily store the exception for - /// retrieval by the caller(s). + /// communicated to all parties waiting on the Request through the Join() + /// method. Implementers should store any errors occuring in the asynchronous + /// parts of their code in a try..catch block (or avoid throwing and just + /// store a new exception) and re-throw them when in ReraiseExceptions() /// /// - /// As with all progressions, the interface contract still requires you to call - /// OnAsyncEnded(), no matter what the outcome of your background operation is. + /// Like in the Waitable class, the contract requires you to always call + /// OnAsyncEnded(), no matter what the outcome of your operation is. /// /// public abstract class Request : Waitable { @@ -65,6 +65,13 @@ namespace Nuclex.Support.Tracking { #endregion // EndedDummyRequest + /// Succeeded dummy request + /// + /// Use to indicate success if the request has already been completed at + /// the time you are asked to perform it. + /// + public static readonly Request SucceededDummy = new EndedDummyRequest(); + /// Creates a new failed dummy request /// Exception that supposedly caused the request to fail /// @@ -83,7 +90,7 @@ namespace Nuclex.Support.Tracking { /// public virtual void Join() { - // If the progression itself hasn't ended yet, block the caller until it has. + // If the request itself hasn't ended yet, block the caller until it has. // We could just use WaitHandle.WaitOne() here, but since the WaitHandle is created // on-the-fly only when it is requested, we can avoid the WaitHandle creation in // case the request is already finished! @@ -109,13 +116,36 @@ namespace Nuclex.Support.Tracking { /// public abstract class Request : Request { - #region class EndedDummyRequest + #region class SucceededDummyRequest - /// Dummy request that is always in the ended state - private class EndedDummyRequest : Request { + /// Succeeded dummy request that is always in the ended state + private class SucceededDummyRequest : Request { + /// Creates a new failed dummy request + /// Result to return to the request's caller + public SucceededDummyRequest(ResultType result) { + this.result = result; + OnAsyncEnded(); + } + /// + /// Allows the specific request implementation to re-throw an exception if + /// the background process finished unsuccessfully + /// + protected override ResultType GatherResults() { + return this.result; + } + /// Results the succeede dummy request will provide to the caller + private ResultType result; + } + + #endregion // SucceededDummyRequest + + #region class FailedDummyRequest + + /// Failed dummy request that is always in the ended state + private class FailedDummyRequest : Request { /// Creates a new failed dummy request /// Exception that caused the dummy to fail - public EndedDummyRequest(Exception exception) { + public FailedDummyRequest(Exception exception) { this.exception = exception; OnAsyncEnded(); } @@ -130,15 +160,24 @@ namespace Nuclex.Support.Tracking { private Exception exception; } - #endregion // EndedDummyRequest + #endregion // FailedDummyRequest + + /// Creates a new failed dummy request + /// Result to provide to the caller + /// + /// A succeeded request that returns the provided result to the caller + /// + public static Request CreateSucceededDummy(ResultType result) { + return new SucceededDummyRequest(result); + } /// Creates a new failed dummy request /// Exception that supposedly caused the request to fail /// /// A failed request that reports the provided exception as cause for its failure /// - public static new Request CreateFailedDummy(Exception exception) { - return new EndedDummyRequest(exception); + public static new Request CreateFailedDummy(Exception exception) { + return new FailedDummyRequest(exception); } /// Waits for the background operation to end diff --git a/Source/Tracking/Waitable.cs b/Source/Tracking/Waitable.cs index 24bff27..a981523 100644 --- a/Source/Tracking/Waitable.cs +++ b/Source/Tracking/Waitable.cs @@ -62,7 +62,7 @@ namespace Nuclex.Support.Tracking { /// A dummy waitable that's always in the 'ended' state /// /// Useful if an operation is already complete when it's being asked for or - /// when a progression that's lazily created is accessed after the original + /// when a waitable that's lazily created is accessed after the original /// operation has ended already. /// public static readonly Waitable EndedDummy = new EndedDummyWaitable(); @@ -186,14 +186,14 @@ namespace Nuclex.Support.Tracking { /// /// /// Calling this method is mandatory. Implementers need to take care that - /// the OnAsyncEnded() method is called on any instance of Progression that's + /// the OnAsyncEnded() method is called on any instance of Waitable that's /// being created. This method also must not be called more than once. /// /// protected virtual void OnAsyncEnded() { - // Make sure the progression is not ended more than once. By guaranteeing that - // a progression can only be ended once, we allow users of this class to + // Make sure the waitable is not ended more than once. By guaranteeing that + // a waitable can only be ended once, we allow users of this class to // skip some safeguards against notifications arriving twice. lock(this) { @@ -202,7 +202,7 @@ namespace Nuclex.Support.Tracking { // to waste any effort optimizing the speed at which an implementation fault // will be noticed. if(this.ended) - throw new InvalidOperationException("The progression has already been ended"); + throw new InvalidOperationException("The Waitable has already been ended"); this.ended = true; @@ -236,7 +236,7 @@ namespace Nuclex.Support.Tracking { protected volatile List endedEventSubscribers; /// Whether the operation has completed yet protected volatile bool ended; - /// Event that will be set when the progression is completed + /// Event that will be set when the waitable is completed /// /// This event is will only be created when it is specifically asked for using /// the WaitHandle property. diff --git a/Source/Tracking/SetProgression.Test.cs b/Source/Tracking/WaitableGroup.Test.cs similarity index 65% rename from Source/Tracking/SetProgression.Test.cs rename to Source/Tracking/WaitableGroup.Test.cs index 551ad06..9fcd81b 100644 --- a/Source/Tracking/SetProgression.Test.cs +++ b/Source/Tracking/WaitableGroup.Test.cs @@ -29,28 +29,28 @@ using NMock2; namespace Nuclex.Support.Tracking { - /// Unit Test for the progression set class + /// Unit Test for the waitable group class [TestFixture] - public class SetProgressionTest { + public class WaitableGroupTest { - #region interface ISetProgressionSubscriber + #region interface IWaitableGroupSubscriber - /// Interface used to test the set progression. - public interface ISetProgressionSubscriber { + /// Interface used to test the set waitable. + public interface IWaitableGroupSubscriber { - /// Called when the set progression's progress changes - /// Set progression whose progress has changed + /// Called when the set waitable's progress changes + /// Waitable group whose progress has changed /// Contains the new progress achieved void ProgressChanged(object sender, ProgressReportEventArgs e); - /// Called when the set progression has ended - /// Set progression that as ended + /// Called when the set waitable has ended + /// Waitable group that as ended /// Not used void Ended(object sender, EventArgs e); } - #endregion // interface ISetProgressionSubscriber + #endregion // interface IWaitableGroupSubscriber #region class ProgressUpdateEventArgsMatcher @@ -93,21 +93,21 @@ namespace Nuclex.Support.Tracking { #region class TestWaitable - /// Progression used for testing in this unit test + /// Waitable used for testing in this unit test private class TestWaitable : Waitable, IProgressReporter { /// will be triggered to report when progress has been achieved public event EventHandler AsyncProgressChanged; - /// Changes the testing progression's indicated progress + /// Changes the testing waitable's indicated progress /// - /// New progress to be reported by the testing progression + /// New progress to be reported by the testing waitable /// public void ChangeProgress(float progress) { OnAsyncProgressChanged(progress); } - /// Transitions the progression into the ended state + /// Transitions the waitable into the ended state public void End() { OnAsyncEnded(); } @@ -115,7 +115,7 @@ namespace Nuclex.Support.Tracking { /// Fires the progress update event /// Progress to report (ranging from 0.0 to 1.0) /// - /// Informs the observers of this progression about the achieved progress. + /// Informs the observers of this waitable about the achieved progress. /// protected virtual void OnAsyncProgressChanged(float progress) { OnAsyncProgressChanged(new ProgressReportEventArgs(progress)); @@ -124,10 +124,10 @@ namespace Nuclex.Support.Tracking { /// Fires the progress update event /// Progress to report (ranging from 0.0 to 1.0) /// - /// Informs the observers of this progression about the achieved progress. - /// Allows for classes derived from the Progression class to easily provide + /// Informs the observers of this waitable about the achieved progress. + /// Allows for classes derived from the Waitable class to easily provide /// a custom event arguments class that has been derived from the - /// Progression's ProgressUpdateEventArgs class. + /// Waitable's ProgressUpdateEventArgs class. /// protected virtual void OnAsyncProgressChanged(ProgressReportEventArgs eventArguments) { EventHandler copy = AsyncProgressChanged; @@ -145,79 +145,79 @@ namespace Nuclex.Support.Tracking { this.mockery = new Mockery(); } - /// Validates that the set progression properly sums the progress + /// Validates that the set waitable properly sums the progress [Test] public void TestSummedProgress() { - SetProgression testSetProgression = - new SetProgression( + WaitableGroup testWaitableGroup = + new WaitableGroup( new TestWaitable[] { new TestWaitable(), new TestWaitable() } ); - ISetProgressionSubscriber mockedSubscriber = mockSubscriber(testSetProgression); + IWaitableGroupSubscriber mockedSubscriber = mockSubscriber(testWaitableGroup); Expect.Once.On(mockedSubscriber). Method("ProgressChanged"). With( new Matcher[] { - new NMock2.Matchers.TypeMatcher(typeof(SetProgression)), + new NMock2.Matchers.TypeMatcher(typeof(WaitableGroup)), new ProgressUpdateEventArgsMatcher(new ProgressReportEventArgs(0.25f)) } ); - testSetProgression.Children[0].Waitable.ChangeProgress(0.5f); + testWaitableGroup.Children[0].Waitable.ChangeProgress(0.5f); this.mockery.VerifyAllExpectationsHaveBeenMet(); } - /// Validates that the set progression respects the weights + /// Validates that the waitable group respects the weights [Test] public void TestWeightedSummedProgress() { - SetProgression testSetProgression = - new SetProgression( + WaitableGroup testWaitableGroup = + new WaitableGroup( new WeightedWaitable[] { new WeightedWaitable(new TestWaitable(), 1.0f), new WeightedWaitable(new TestWaitable(), 2.0f) } ); - ISetProgressionSubscriber mockedSubscriber = mockSubscriber(testSetProgression); + IWaitableGroupSubscriber mockedSubscriber = mockSubscriber(testWaitableGroup); Expect.Once.On(mockedSubscriber). Method("ProgressChanged"). With( new Matcher[] { - new NMock2.Matchers.TypeMatcher(typeof(SetProgression)), + new NMock2.Matchers.TypeMatcher(typeof(WaitableGroup)), new ProgressUpdateEventArgsMatcher(new ProgressReportEventArgs(0.5f / 3.0f)) } ); - testSetProgression.Children[0].Waitable.ChangeProgress(0.5f); + testWaitableGroup.Children[0].Waitable.ChangeProgress(0.5f); Expect.Once.On(mockedSubscriber). Method("ProgressChanged"). With( new Matcher[] { - new NMock2.Matchers.TypeMatcher(typeof(SetProgression)), + new NMock2.Matchers.TypeMatcher(typeof(WaitableGroup)), new ProgressUpdateEventArgsMatcher(new ProgressReportEventArgs(0.5f)) } ); - testSetProgression.Children[1].Waitable.ChangeProgress(0.5f); + testWaitableGroup.Children[1].Waitable.ChangeProgress(0.5f); this.mockery.VerifyAllExpectationsHaveBeenMet(); } /// - /// Validates that the ended event is triggered when the last progression ends + /// Validates that the ended event is triggered when the last waitable ends /// [Test] public void TestEndedEvent() { - SetProgression testSetProgression = - new SetProgression( + WaitableGroup testWaitableGroup = + new WaitableGroup( new TestWaitable[] { new TestWaitable(), new TestWaitable() } ); - ISetProgressionSubscriber mockedSubscriber = mockSubscriber(testSetProgression); + IWaitableGroupSubscriber mockedSubscriber = mockSubscriber(testWaitableGroup); Expect.Exactly(2).On(mockedSubscriber). Method("ProgressChanged"). @@ -227,21 +227,21 @@ namespace Nuclex.Support.Tracking { Method("Ended"). WithAnyArguments(); - testSetProgression.Children[0].Waitable.End(); - testSetProgression.Children[1].Waitable.End(); + testWaitableGroup.Children[0].Waitable.End(); + testWaitableGroup.Children[1].Waitable.End(); this.mockery.VerifyAllExpectationsHaveBeenMet(); } - /// Mocks a subscriber for the events of a progression - /// Progression to mock an event subscriber for + /// Mocks a subscriber for the events of a waitable + /// Waitable to mock an event subscriber for /// The mocked event subscriber - private ISetProgressionSubscriber mockSubscriber(Waitable progression) { - ISetProgressionSubscriber mockedSubscriber = - this.mockery.NewMock(); + private IWaitableGroupSubscriber mockSubscriber(Waitable waitable) { + IWaitableGroupSubscriber mockedSubscriber = + this.mockery.NewMock(); - progression.AsyncEnded += new EventHandler(mockedSubscriber.Ended); - (progression as IProgressReporter).AsyncProgressChanged += + waitable.AsyncEnded += new EventHandler(mockedSubscriber.Ended); + (waitable as IProgressReporter).AsyncProgressChanged += new EventHandler(mockedSubscriber.ProgressChanged); return mockedSubscriber; diff --git a/Source/Tracking/SetProgression.cs b/Source/Tracking/WaitableGroup.cs similarity index 50% rename from Source/Tracking/SetProgression.cs rename to Source/Tracking/WaitableGroup.cs index 05743e5..ff24fb7 100644 --- a/Source/Tracking/SetProgression.cs +++ b/Source/Tracking/WaitableGroup.cs @@ -26,66 +26,66 @@ using Nuclex.Support.Collections; namespace Nuclex.Support.Tracking { - /// Forms a single progression from a set of progressions - /// Type of progressions to manage as a set - public class SetProgression : Waitable, IDisposable, IProgressReporter - where ProgressionType : Waitable { + /// Forms a single waitable from a group of waitables + /// Type of waitables to manage as a set + public class WaitableGroup : Waitable, IDisposable, IProgressReporter + where WaitableType : Waitable { /// will be triggered to report when progress has been achieved public event EventHandler AsyncProgressChanged; - /// Initializes a new set progression - /// Progressions to track with this set + /// Initializes a new waitable group + /// Waitables to track with this group /// - /// Uses a default weighting factor of 1.0 for all progressions. + /// Uses a default weighting factor of 1.0 for all waitables. /// - public SetProgression(IEnumerable childs) + public WaitableGroup(IEnumerable childs) : this() { - // Construct a WeightedProgression with the default weight for each - // progression and wrap it in an ObservedProgression - foreach(ProgressionType progression in childs) { + // Construct a WeightedWaitable with the default weight for each + // waitable and wrap it in an ObservedWaitable + foreach(WaitableType waitable in childs) { this.children.Add( - new ObservedWeightedWaitable( - new WeightedWaitable(progression), - new ObservedWeightedWaitable.ReportDelegate(asyncProgressUpdated), - new ObservedWeightedWaitable.ReportDelegate(asyncEnded) + new ObservedWeightedWaitable( + new WeightedWaitable(waitable), + new ObservedWeightedWaitable.ReportDelegate(asyncProgressUpdated), + new ObservedWeightedWaitable.ReportDelegate(asyncChildEnded) ) ); } - // Since all progressions have a weight of 1.0, the total weight is - // equal to the number of progressions in our list + // Since all waitables have a weight of 1.0, the total weight is + // equal to the number of waitables in our list this.totalWeight = (float)this.children.Count; } - /// Initializes a new set progression - /// Progressions to track with this set - public SetProgression( - IEnumerable> childs + /// Initializes a new waitable group + /// Waitables to track with this group + public WaitableGroup( + IEnumerable> childs ) : this() { - // Construct an ObservedProgression around each of the WeightedProgressions - foreach(WeightedWaitable progression in childs) { + // Construct an ObservedWaitable around each of the WeightedWaitables + foreach(WeightedWaitable waitable in childs) { this.children.Add( - new ObservedWeightedWaitable( - progression, - new ObservedWeightedWaitable.ReportDelegate(asyncProgressUpdated), - new ObservedWeightedWaitable.ReportDelegate(asyncEnded) + new ObservedWeightedWaitable( + waitable, + new ObservedWeightedWaitable.ReportDelegate(asyncProgressUpdated), + new ObservedWeightedWaitable.ReportDelegate(asyncChildEnded) ) ); // Sum up the total weight - this.totalWeight += progression.Weight; + this.totalWeight += waitable.Weight; } } /// Performs common initialization for the public constructors - private SetProgression() { - this.children = new List>(); + private WaitableGroup() { + this.children = new List>(); } /// Immediately releases all resources owned by the object @@ -93,8 +93,8 @@ namespace Nuclex.Support.Tracking { if(this.children != null) { - // Dispose all the observed progressions, disconnecting the events from the - // actual progressions so the GC can more easily collect this class + // Dispose all the observed waitables, disconnecting the events from the + // actual waitables so the GC can more easily collect this class for(int index = 0; index < this.children.Count; ++index) this.children[index].Dispose(); @@ -105,18 +105,18 @@ namespace Nuclex.Support.Tracking { } - /// Childs contained in the progression set - public IList> Children { + /// Childs contained in the waitable set + public IList> Children { get { // The wrapper is constructed only when needed. Most of the time, users will - // just create a SetProgression and monitor its progress without ever using + // just create a waitable group and monitor its progress without ever using // the Childs collection. if(this.wrapper == null) { // This doesn't need a lock because it's a stateless wrapper. // If it is constructed twice, then so be it, no problem at all. - this.wrapper = new WeightedProgressionWrapperCollection( + this.wrapper = new WeightedWaitableWrapperCollection( this.children ); @@ -130,7 +130,7 @@ namespace Nuclex.Support.Tracking { /// Fires the progress update event /// Progress to report (ranging from 0.0 to 1.0) /// - /// Informs the observers of this progression about the achieved progress. + /// Informs the observers of this waitables about the achieved progress. /// protected virtual void OnAsyncProgressChanged(float progress) { OnAsyncProgressChanged(new ProgressReportEventArgs(progress)); @@ -139,10 +139,10 @@ namespace Nuclex.Support.Tracking { /// Fires the progress update event /// Progress to report (ranging from 0.0 to 1.0) /// - /// Informs the observers of this progression about the achieved progress. - /// Allows for classes derived from the Progression class to easily provide + /// Informs the observers of this waitable about the achieved progress. + /// Allows for classes derived from the Waitable class to easily provide /// a custom event arguments class that has been derived from the - /// Progression's ProgressUpdateEventArgs class. + /// waitable's ProgressUpdateEventArgs class. /// protected virtual void OnAsyncProgressChanged(ProgressReportEventArgs eventArguments) { EventHandler copy = AsyncProgressChanged; @@ -151,13 +151,13 @@ namespace Nuclex.Support.Tracking { } /// - /// Called when the progress of one of the observed progressions changes + /// Called when the progress of one of the observed waitables changes /// private void asyncProgressUpdated() { float totalProgress = 0.0f; - // Calculate the sum of the progress reported by our child progressions, - // scaled to the weight each progression has assigned to it. + // Calculate the sum of the progress reported by our child waitables, + // scaled to the weight each waitable has assigned to it. for(int index = 0; index < this.children.Count; ++index) { totalProgress += this.children[index].Progress * this.children[index].WeightedWaitable.Weight; @@ -172,29 +172,29 @@ namespace Nuclex.Support.Tracking { } /// - /// Called when an observed progression ends + /// Called when an observed waitable ends /// - private void asyncEnded() { + private void asyncChildEnded() { - // If there's still at least one progression going, don't report that - // the SetProgression has finished yet. + // If there's still at least one waitable going, don't report that + // the waitable group has finished yet. for(int index = 0; index < this.children.Count; ++index) if(!this.children[index].WeightedWaitable.Waitable.Ended) return; - // All child progressions have ended, so the set has now ended as well + // All child waitables have ended, so the set has now ended as well OnAsyncEnded(); } - /// Progressions being managed in the set - private List> children; + /// Waitables being managed in the set + private List> children; /// - /// Wrapper collection for exposing the child progressions under the - /// WeightedProgression interface + /// Wrapper collection for exposing the child waitables under the + /// WeightedWaitable interface /// - private volatile WeightedProgressionWrapperCollection wrapper; - /// Summed weight of all progressions in the set + private volatile WeightedWaitableWrapperCollection wrapper; + /// Summed weight of all waitables in the set private float totalWeight; } diff --git a/Source/Tracking/WeightedWaitable.cs b/Source/Tracking/WeightedWaitable.cs index 6855e0f..3a0ed56 100644 --- a/Source/Tracking/WeightedWaitable.cs +++ b/Source/Tracking/WeightedWaitable.cs @@ -23,36 +23,36 @@ using System.Collections.Generic; namespace Nuclex.Support.Tracking { - /// Progression with an associated weight for the total progress - public class WeightedWaitable where ProgressionType : Waitable { + /// Waitable with an associated weight for the total progress + public class WeightedWaitable where WaitableType : Waitable { /// - /// Initializes a new weighted progression with a default weight of 1.0 + /// Initializes a new weighted waitable with a default weight of 1.0 /// - /// Progression whose progress to monitor - public WeightedWaitable(ProgressionType progression) : this(progression, 1.0f) { } + /// Waitable whose progress to monitor + public WeightedWaitable(WaitableType waitable) : this(waitable, 1.0f) { } - /// Initializes a new weighted progression - /// Progression whose progress to monitor - /// Weighting of the progression's progress - public WeightedWaitable(ProgressionType progression, float weight) { - this.progression = progression; + /// Initializes a new weighted waitable + /// Waitable whose progress to monitor + /// Weighting of the waitable's progress + public WeightedWaitable(WaitableType waitable, float weight) { + this.waitable = waitable; this.weight = weight; } - /// Progression being wrapped by this weighted progression - public ProgressionType Waitable { - get { return this.progression; } + /// Waitable being wrapped by this weighted waitable + public WaitableType Waitable { + get { return this.waitable; } } - /// The contribution of this progression to the total progress + /// The contribution of this waitable to the total progress public float Weight { get { return this.weight; } } - /// Progression whose progress we're tracking - private ProgressionType progression; - /// Weighting of this progression in the total progress + /// Waitable whose progress we're tracking + private WaitableType waitable; + /// Weighting of this waitable in the total progress private float weight; }