Some more unit tests; improved documentation; improve useless speed optimization of an exceptional case
git-svn-id: file:///srv/devel/repo-conversion/nusu@39 d2e56fa2-650e-0410-a79f-9358c0239efd
This commit is contained in:
parent
81cb56f468
commit
acbb07d6b5
|
@ -39,24 +39,13 @@ namespace Nuclex.Support.Scheduling {
|
|||
/// </remarks>
|
||||
public virtual void End() {
|
||||
|
||||
// Use some ingenious double-checked locking to set the endCalled flag.
|
||||
// Quite a lot of effort for a mere safety feature that prevents the programmer
|
||||
// from calling End() twice.
|
||||
bool error;
|
||||
if(!this.endCalled) {
|
||||
lock(this) {
|
||||
if(!this.endCalled) {
|
||||
this.endCalled = true;
|
||||
error = false;
|
||||
} else {
|
||||
error = true;
|
||||
}
|
||||
} // lock
|
||||
} else {
|
||||
error = true;
|
||||
// By design, end can only be called once!
|
||||
lock(this) {
|
||||
if(this.endCalled)
|
||||
throw new InvalidOperationException("End() has already been called");
|
||||
|
||||
this.endCalled = true;
|
||||
}
|
||||
if(error)
|
||||
throw new InvalidOperationException("End() has already been called");
|
||||
|
||||
// If the progression itself hasn't ended yet, block the caller until it has.
|
||||
if(!Ended)
|
||||
|
|
|
@ -302,6 +302,25 @@ namespace Nuclex.Support.Tracking {
|
|||
this.mockery.VerifyAllExpectationsHaveBeenMet();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to provoke a deadlock by re-entering the tracker from one of
|
||||
/// its own events.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestProvokedDeadlock() {
|
||||
ProgressionTracker tracker = new ProgressionTracker();
|
||||
|
||||
TestProgression test1 = new TestProgression();
|
||||
tracker.Track(test1);
|
||||
|
||||
tracker.AsyncIdleStateChanged +=
|
||||
(EventHandler<IdleStateEventArgs>)delegate(object sender, IdleStateEventArgs arguments) {
|
||||
tracker.Track(Progression.EndedDummy);
|
||||
};
|
||||
|
||||
test1.End();
|
||||
}
|
||||
|
||||
/// <summary>Mocks a subscriber for the events of a tracker</summary>
|
||||
/// <param name="tracker">Tracker to mock an event subscriber for</param>
|
||||
/// <returns>The mocked event subscriber</returns>
|
||||
|
|
|
@ -189,7 +189,7 @@ namespace Nuclex.Support.Tracking {
|
|||
observedProgression.Dispose();
|
||||
}
|
||||
|
||||
}
|
||||
} // if progression ended
|
||||
|
||||
} // lock
|
||||
|
||||
|
@ -213,6 +213,7 @@ namespace Nuclex.Support.Tracking {
|
|||
{
|
||||
ObservedWeightedProgression<Progression> wrappedProgression =
|
||||
this.trackedProgressions[removeIndex];
|
||||
|
||||
this.trackedProgressions.RemoveAt(removeIndex);
|
||||
wrappedProgression.Dispose();
|
||||
}
|
||||
|
@ -295,7 +296,7 @@ namespace Nuclex.Support.Tracking {
|
|||
this.progress = totalProgress;
|
||||
OnAsyncProgressUpdated(totalProgress);
|
||||
|
||||
}
|
||||
} // lock
|
||||
}
|
||||
|
||||
/// <summary>Called when one of the tracked progressions has ended</summary>
|
||||
|
@ -319,7 +320,7 @@ namespace Nuclex.Support.Tracking {
|
|||
// progressions were finished, so it's safe to trigger this here.
|
||||
setIdle(true);
|
||||
|
||||
}
|
||||
} // lock
|
||||
}
|
||||
|
||||
/// <summary>Called when one of the tracked progression has achieved progress</summary>
|
||||
|
@ -338,6 +339,10 @@ namespace Nuclex.Support.Tracking {
|
|||
OnAsyncIdleStateChanged(idle);
|
||||
}
|
||||
|
||||
/// <summary>Whether the tracker is currently idle</summary>
|
||||
private volatile bool idle;
|
||||
/// <summary>Current summed progress of the tracked progressions</summary>
|
||||
private volatile float progress;
|
||||
/// <summary>Total weight of all progressions being tracked</summary>
|
||||
private volatile float totalWeight;
|
||||
/// <summary>Progressions being tracked by this tracker</summary>
|
||||
|
@ -346,10 +351,6 @@ namespace Nuclex.Support.Tracking {
|
|||
private ObservedWeightedProgression<Progression>.ReportDelegate asyncEndedDelegate;
|
||||
/// <summary>Delegate for the asyncProgressUpdated() method</summary>
|
||||
private ObservedWeightedProgression<Progression>.ReportDelegate asyncProgressUpdatedDelegate;
|
||||
/// <summary>Whether the tracker is currently idle</summary>
|
||||
private bool idle;
|
||||
/// <summary>Current summed progress of the tracked progressions</summary>
|
||||
private volatile float progress;
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user