Added an AsyncStarted event to the progression class, currently disabled for further consideration; set up the outline of a new spatial partitioning framework with an R*-Tree implementation; new AbortedException for indicating that a process was forcefully aborted
git-svn-id: file:///srv/devel/repo-conversion/nusu@31 d2e56fa2-650e-0410-a79f-9358c0239efd
This commit is contained in:
parent
6d79fe3ebc
commit
1ae0c7de63
|
@ -162,6 +162,10 @@
|
|||
<Name>SimpleRectanglePacker.Test</Name>
|
||||
<DependentUpon>SimpleRectanglePacker.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Source\Scheduling\AbortedException.cs">
|
||||
<XNAUseContentPipeline>false</XNAUseContentPipeline>
|
||||
<Name>AbortedException</Name>
|
||||
</Compile>
|
||||
<Compile Include="Source\Serialization\BinarySerializer.Test.cs">
|
||||
<XNAUseContentPipeline>false</XNAUseContentPipeline>
|
||||
<Name>BinarySerializer.Test</Name>
|
||||
|
@ -179,6 +183,26 @@
|
|||
<XNAUseContentPipeline>false</XNAUseContentPipeline>
|
||||
<Name>IAbortable</Name>
|
||||
</Compile>
|
||||
<Compile Include="Source\SpatialPartitioning\BoundingRectangle.cs">
|
||||
<XNAUseContentPipeline>false</XNAUseContentPipeline>
|
||||
<Name>BoundingRectangle</Name>
|
||||
</Compile>
|
||||
<Compile Include="Source\SpatialPartitioning\RTree2.cs">
|
||||
<XNAUseContentPipeline>false</XNAUseContentPipeline>
|
||||
<Name>RTree2</Name>
|
||||
</Compile>
|
||||
<Compile Include="Source\SpatialPartitioning\RTreeLeaf2.cs">
|
||||
<XNAUseContentPipeline>false</XNAUseContentPipeline>
|
||||
<Name>RTreeLeaf2</Name>
|
||||
</Compile>
|
||||
<Compile Include="Source\SpatialPartitioning\RTreeNode2.cs">
|
||||
<XNAUseContentPipeline>false</XNAUseContentPipeline>
|
||||
<Name>RTreeNode2</Name>
|
||||
</Compile>
|
||||
<Compile Include="Source\SpatialPartitioning\SpatialIndex2.cs">
|
||||
<XNAUseContentPipeline>false</XNAUseContentPipeline>
|
||||
<Name>SpatialIndex2</Name>
|
||||
</Compile>
|
||||
<Compile Include="Source\Tracking\Internal\ObservedProgression.cs">
|
||||
<XNAUseContentPipeline>false</XNAUseContentPipeline>
|
||||
<Name>ObservedProgression</Name>
|
||||
|
|
|
@ -25,7 +25,8 @@ namespace Nuclex.Support.Collections {
|
|||
|
||||
/// <summary>Queue that dequeues items in order of their priority</summary>
|
||||
public class UnintrusivePriorityQueue<ItemType, PriorityType>
|
||||
: ICollection, IEnumerable<ItemType> where PriorityType : IComparable<PriorityType> {
|
||||
: ICollection, IEnumerable<ItemType>
|
||||
where PriorityType : IComparable<PriorityType> {
|
||||
|
||||
#region struct Entry
|
||||
|
||||
|
|
56
Source/Scheduling/AbortedException.cs
Normal file
56
Source/Scheduling/AbortedException.cs
Normal file
|
@ -0,0 +1,56 @@
|
|||
#region CPL License
|
||||
/*
|
||||
Nuclex Framework
|
||||
Copyright (C) 2002-2007 Nuclex Development Labs
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the IBM Common Public License as
|
||||
published by the IBM Corporation; either version 1.0 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
IBM Common Public License for more details.
|
||||
|
||||
You should have received a copy of the IBM Common Public
|
||||
License along with this library
|
||||
*/
|
||||
#endregion
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Nuclex.Support.Scheduling {
|
||||
|
||||
/// <summary>Indicates that an operation has been forcefully aborted</summary>
|
||||
/// <remarks>
|
||||
/// This exception is the typical result of using AsyncAbort() on a running
|
||||
/// background process.
|
||||
/// </remarks>
|
||||
[Serializable]
|
||||
public class AbortedException : ApplicationException {
|
||||
|
||||
/// <summary>Initializes the exception</summary>
|
||||
public AbortedException() { }
|
||||
|
||||
/// <summary>Initializes the exception with an error message</summary>
|
||||
/// <param name="message">Error message describing the cause of the exception</param>
|
||||
public AbortedException(string message) : base(message) { }
|
||||
|
||||
/// <summary>Initializes the exception as a followup exception</summary>
|
||||
/// <param name="message">Error message describing the cause of the exception</param>
|
||||
/// <param name="inner">Preceding exception that has caused this exception</param>
|
||||
public AbortedException(string message, Exception inner) : base(message, inner) { }
|
||||
|
||||
/// <summary>Initializes the exception from its serialized state</summary>
|
||||
/// <param name="info">Contains the serialized fields of the exception</param>
|
||||
/// <param name="context">Additional environmental informations</param>
|
||||
protected AbortedException(
|
||||
System.Runtime.Serialization.SerializationInfo info,
|
||||
System.Runtime.Serialization.StreamingContext context
|
||||
)
|
||||
: base(info, context) { }
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.Scheduling
|
|
@ -19,16 +19,23 @@ License along with this library
|
|||
#endregion
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Nuclex.Support.Tracking {
|
||||
namespace Nuclex.Support.Scheduling {
|
||||
|
||||
/// <summary>Interface for abortable processes</summary>
|
||||
public interface IAbortable {
|
||||
|
||||
/// <summary>Aborts the running process. Can be called from any thread.</summary>
|
||||
/// <remarks>
|
||||
/// The receive should honor the abort request and stop whatever it is
|
||||
/// doing as soon as possible. The method does not impose any requirement
|
||||
/// on the timeliness of the reaction of the running process, but implementers
|
||||
/// are advised to not ignore the abort request and try to design their code
|
||||
/// in such a way that it can be stopped in a reasonable time
|
||||
/// (eg. within 1 second of the abort request).
|
||||
/// </remarks>
|
||||
void AsyncAbort();
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.Tracking
|
||||
} // namespace Nuclex.Support.Scheduling
|
||||
|
|
|
@ -19,24 +19,17 @@ License along with this library
|
|||
#endregion
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Nuclex.Support.Tracking {
|
||||
using Nuclex.Support.Tracking;
|
||||
|
||||
namespace Nuclex.Support.Scheduling {
|
||||
|
||||
/// <summary>Base class for observable operations running in the background</summary>
|
||||
public abstract class Operation : Progression {
|
||||
|
||||
/// <summary>Executes the operation</summary>
|
||||
/// <summary>Launches the background operation</summary>
|
||||
public abstract void Start();
|
||||
|
||||
/// <summary>
|
||||
/// Executes the operation synchronously, blocking the calling thread
|
||||
/// </summary>
|
||||
public virtual void Execute() {
|
||||
Start();
|
||||
WaitHandle.WaitOne();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.Tracking
|
||||
} // namespace Nuclex.Support.Scheduling
|
||||
|
|
|
@ -19,11 +19,10 @@ License along with this library
|
|||
#endregion
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Nuclex.Support.Tracking {
|
||||
namespace Nuclex.Support.Scheduling {
|
||||
/*
|
||||
public class ThreadedMethodOperation : Operation {
|
||||
}
|
||||
*/
|
||||
} // namespace Nuclex.Support.Tracking
|
||||
} // namespace Nuclex.Support.Scheduling
|
||||
|
|
78
Source/SpatialPartitioning/BoundingRectangle.cs
Normal file
78
Source/SpatialPartitioning/BoundingRectangle.cs
Normal file
|
@ -0,0 +1,78 @@
|
|||
#region CPL License
|
||||
/*
|
||||
Nuclex Framework
|
||||
Copyright (C) 2002-2007 Nuclex Development Labs
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the IBM Common Public License as
|
||||
published by the IBM Corporation; either version 1.0 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
IBM Common Public License for more details.
|
||||
|
||||
You should have received a copy of the IBM Common Public
|
||||
License along with this library
|
||||
*/
|
||||
#endregion
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace Nuclex.Support.SpatialPartitioning {
|
||||
|
||||
/// <summary>Two-dimensional bounding rectangle</summary>
|
||||
internal struct BoundingRectangle {
|
||||
|
||||
/// <summary>Initializes a new two-dimensional bounding rectangle</summary>
|
||||
/// <param name="min">Lesser coordinates of the bounding rectangle</param>
|
||||
/// <param name="max">Greater coordinates of the bounding rectangle</param>
|
||||
public BoundingRectangle(Vector2 min, Vector2 max) {
|
||||
this.Min = min;
|
||||
this.Max = max;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Builds the smallest bounding rectangle that contains the two
|
||||
/// specified bounding rectangle.
|
||||
/// </summary>
|
||||
/// <param name="original">One of the bounding rectangles to contain</param>
|
||||
/// <param name="additional">One of the bounding rectangles to contain</param>
|
||||
/// <returns>The resulting merged bounding rectangle</returns>
|
||||
public static BoundingRectangle CreateMerged(
|
||||
BoundingRectangle original, BoundingRectangle additional
|
||||
) {
|
||||
BoundingRectangle result;
|
||||
CreateMerged(ref original, ref additional, out result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Builds the smallest bounding rectangle that contains the two
|
||||
/// specified bounding rectangle.
|
||||
/// </summary>
|
||||
/// <param name="original">One of the bounding rectangles to contain</param>
|
||||
/// <param name="additional">One of the bounding rectangles to contain</param>
|
||||
/// <param name="result">The resulting merged bounding rectangle</param>
|
||||
public static void CreateMerged(
|
||||
ref BoundingRectangle original, ref BoundingRectangle additional,
|
||||
out BoundingRectangle result
|
||||
) {
|
||||
result = new BoundingRectangle();
|
||||
result.Min = Vector2.Min(original.Min, additional.Min);
|
||||
result.Max = Vector2.Max(original.Max, additional.Max);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>Coordinates of the lesser side of the bounding rectangle</summary>
|
||||
public Vector2 Min;
|
||||
|
||||
/// <summary>Coordinates of the greater side of the bounding rectangle</summary>
|
||||
public Vector2 Max;
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.SpatialPartitioning
|
95
Source/SpatialPartitioning/RTree2.cs
Normal file
95
Source/SpatialPartitioning/RTree2.cs
Normal file
|
@ -0,0 +1,95 @@
|
|||
#region CPL License
|
||||
/*
|
||||
Nuclex Framework
|
||||
Copyright (C) 2002-2007 Nuclex Development Labs
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the IBM Common Public License as
|
||||
published by the IBM Corporation; either version 1.0 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
IBM Common Public License for more details.
|
||||
|
||||
You should have received a copy of the IBM Common Public
|
||||
License along with this library
|
||||
*/
|
||||
#endregion
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace Nuclex.Support.SpatialPartitioning {
|
||||
|
||||
/// <summary>R-Tree for two-dimensional data</summary>
|
||||
/// <remarks>
|
||||
/// R-Trees essentially fullfill the same role that is traditionally
|
||||
/// assigned to quadtrees in games. But unlike a quadtree, an R-Tree does not
|
||||
/// require knowledge of the total area that is to be covered by the objects
|
||||
/// that will populate the tree.
|
||||
/// </remarks>
|
||||
public partial class RTree2<ItemType> : SpatialIndex2 {
|
||||
|
||||
/// <summary>Variants of R-Tree behaviors this implementation can assume</summary>
|
||||
public enum Variants {
|
||||
|
||||
/// <summary>
|
||||
/// Insertions and deletions take linear time at the cost of degrading the
|
||||
/// tree's overall performance.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Finds the two bounding boxes with the greatest normalized separation
|
||||
/// along both axes, and split along this axis. The remaining bounding boxes
|
||||
/// in the node are assigned to the nodes whose covering bounding box is
|
||||
/// increased the least by the addition [Gutt84]. This method takes linear time.
|
||||
/// </remarks>
|
||||
Linear,
|
||||
|
||||
/// <summary>
|
||||
/// Insertions and deletions take quadratic time while keeping the tree's
|
||||
/// overall performance at a reasonable level.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Examines all the children of the overflowing node and find the pair of
|
||||
/// bounding boxes that would waste the most area were they to be inserted
|
||||
/// in the same node. This is determined by subtracting the sum of the areas
|
||||
/// of the two bounding boxes from the area of the covering bounding box.
|
||||
/// These two bounding boxes are placed in separate nodes, say j and k.
|
||||
/// The set of remaining bounding boxes are examined and the bounding box i
|
||||
/// whose addition maximizes the difference in coverage between the bounding
|
||||
/// boxes associated with j and k is added to the node whose coverage
|
||||
/// is minimized by the addition. This process is reapplied to the
|
||||
/// remaining bounding boxes [Gutt84]. This method takes quadratic time.
|
||||
/// </remarks>
|
||||
Quadratic,
|
||||
|
||||
/// <summary>
|
||||
/// Insertions and deletions vary in performance but the tree's overall
|
||||
/// performance is kept high.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The R*-tree [Beck90c] is a name given to a variant of the R-tree which
|
||||
/// makes use of the most complex of the node splitting algorithms. The
|
||||
/// algorithm differs from the other algorithms as it attempts to reduce
|
||||
/// both overlap and coverage. In particular, the primary focus is on
|
||||
/// reducing overlap with ties broken by favoring the splits that reduce
|
||||
/// the coverage by using the splits that minimize the perimeter of the
|
||||
/// bounding boxes of the resulting nodes. In addition, when a node 'a'
|
||||
/// overflows, instead of immediately splitting 'a', an attempt is made
|
||||
/// first to see if some of the objects in 'a' could possibly be more suited
|
||||
/// to being in another node. This is achieved by reinserting a fraction
|
||||
/// (30% has been found to yield good performance [Beck90c]) of these
|
||||
/// objects in the tree (termed 'forced reinsertion'). The node is only split
|
||||
/// if it has been found to overflow after reinsertion has taken place.
|
||||
/// This method is quite complex.
|
||||
/// </remarks>
|
||||
RStar
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Geometry.SpatialPartitioning
|
35
Source/SpatialPartitioning/RTreeLeaf2.cs
Normal file
35
Source/SpatialPartitioning/RTreeLeaf2.cs
Normal file
|
@ -0,0 +1,35 @@
|
|||
#region CPL License
|
||||
/*
|
||||
Nuclex Framework
|
||||
Copyright (C) 2002-2007 Nuclex Development Labs
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the IBM Common Public License as
|
||||
published by the IBM Corporation; either version 1.0 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
IBM Common Public License for more details.
|
||||
|
||||
You should have received a copy of the IBM Common Public
|
||||
License along with this library
|
||||
*/
|
||||
#endregion
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Nuclex.Support.SpatialPartitioning {
|
||||
|
||||
/// <summary>Leaf of an R-Tree</summary>
|
||||
internal class RTreeLeaf2<ItemType> {
|
||||
|
||||
public BoundingRectangle BoundingRectangle;
|
||||
public ItemType Item;
|
||||
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.SpatialPartitioning
|
65
Source/SpatialPartitioning/RTreeNode2.cs
Normal file
65
Source/SpatialPartitioning/RTreeNode2.cs
Normal file
|
@ -0,0 +1,65 @@
|
|||
#region CPL License
|
||||
/*
|
||||
Nuclex Framework
|
||||
Copyright (C) 2002-2007 Nuclex Development Labs
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the IBM Common Public License as
|
||||
published by the IBM Corporation; either version 1.0 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
IBM Common Public License for more details.
|
||||
|
||||
You should have received a copy of the IBM Common Public
|
||||
License along with this library
|
||||
*/
|
||||
#endregion
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Nuclex.Support.SpatialPartitioning {
|
||||
|
||||
/// <summary>Node in a two-dimensional R-Tree</summary>
|
||||
/// <typeparam name="ItemType">Type of items that the R-Tree manages</typeparam>
|
||||
internal class RTreeNode2<ItemType> {
|
||||
|
||||
/// <summary>Initializes a new R-Tree node</summary>
|
||||
/// <param name="capacity">Number of items that can fit in the node</param>
|
||||
public RTreeNode2(int capacity) {
|
||||
this.leafs = new RTreeLeaf2<ItemType>[capacity];
|
||||
}
|
||||
|
||||
/// <summary>Inserts an item into this node</summary>
|
||||
/// <param name="item">Item to be inserted</param>
|
||||
/// <param name="boundingRectangle">Bounding rectangle of the item</param>
|
||||
private void insertEntry(ItemType item, BoundingRectangle boundingRectangle) {
|
||||
Debug.Assert(leafCount < this.leafs.Length);
|
||||
|
||||
this.leafs[this.leafCount].Item = item;
|
||||
this.leafs[this.leafCount].BoundingRectangle = boundingRectangle;
|
||||
|
||||
BoundingRectangle.CreateMerged(
|
||||
ref this.boundingRectangle, ref boundingRectangle,
|
||||
out this.boundingRectangle
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>The node's minimum bounding rectangle</summary>
|
||||
/// <remarks>
|
||||
/// This bounding rectangle is just large enough to contain all the items
|
||||
/// belonging to this node and recursively all of its child nodes.
|
||||
/// </remarks>
|
||||
private BoundingRectangle boundingRectangle;
|
||||
|
||||
/// <summary>Leafs of this node</summary>
|
||||
private RTreeLeaf2<ItemType>[] leafs;
|
||||
/// <summary>Number of leafes in use</summary>
|
||||
private int leafCount;
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.SpatialPartitioning
|
30
Source/SpatialPartitioning/SpatialIndex2.cs
Normal file
30
Source/SpatialPartitioning/SpatialIndex2.cs
Normal file
|
@ -0,0 +1,30 @@
|
|||
#region CPL License
|
||||
/*
|
||||
Nuclex Framework
|
||||
Copyright (C) 2002-2007 Nuclex Development Labs
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the IBM Common Public License as
|
||||
published by the IBM Corporation; either version 1.0 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
IBM Common Public License for more details.
|
||||
|
||||
You should have received a copy of the IBM Common Public
|
||||
License along with this library
|
||||
*/
|
||||
#endregion
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Nuclex.Support.SpatialPartitioning {
|
||||
|
||||
/// <summary>Interface for a 2D geometrical database</summary>
|
||||
public abstract class SpatialIndex2 {
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.SpatialPartitioning
|
|
@ -45,10 +45,13 @@ namespace Nuclex.Support.Tracking {
|
|||
#region class EndedDummyProgression
|
||||
|
||||
/// <summary>Dummy progression which always is in the 'ended' state</summary>
|
||||
internal class EndedDummyProgression : Progression {
|
||||
private class EndedDummyProgression : Progression {
|
||||
|
||||
/// <summary>Initializes a new ended dummy progression</summary>
|
||||
public EndedDummyProgression() {
|
||||
#if PROGRESSION_STARTABLE
|
||||
OnAsyncStarted();
|
||||
#endif
|
||||
OnAsyncEnded();
|
||||
}
|
||||
|
||||
|
@ -67,14 +70,42 @@ namespace Nuclex.Support.Tracking {
|
|||
/// <summary>will be triggered to report when progress has been achieved</summary>
|
||||
public event EventHandler<ProgressUpdateEventArgs> AsyncProgressUpdated;
|
||||
|
||||
#if PROGRESSION_STARTABLE
|
||||
/// <summary>Will be triggered when the progression has ended</summary>
|
||||
public event EventHandler AsyncStarted;
|
||||
#endif
|
||||
|
||||
/// <summary>Will be triggered when the progression has ended</summary>
|
||||
public event EventHandler AsyncEnded;
|
||||
|
||||
#if PROGRESSION_STARTABLE
|
||||
/// <summary>True when the progression has been started.</summary>
|
||||
/// <remarks>
|
||||
/// This is also true if the progression has been started but is already finished.
|
||||
/// To find out whether the progression is running just now, use the IsRunning
|
||||
/// property instead.
|
||||
/// </remarks>
|
||||
public bool Started {
|
||||
get { return this.started; }
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>Whether the progression has ended already</summary>
|
||||
public bool Ended {
|
||||
get { return this.ended; }
|
||||
}
|
||||
|
||||
#if PROGRESSION_STARTABLE
|
||||
/// <summary>Whether the progression is currently executing.</summary>
|
||||
/// <remarks>
|
||||
/// This property is true when the progression is executing right at the time of
|
||||
/// the call (eg. when it has been started and has not ended yet).
|
||||
/// </remarks>
|
||||
public bool IsRunning {
|
||||
get { return (this.started && !base.Ended); }
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>WaitHandle that can be used to wait for the progression to end</summary>
|
||||
public WaitHandle WaitHandle {
|
||||
get {
|
||||
|
@ -88,7 +119,7 @@ namespace Nuclex.Support.Tracking {
|
|||
// the second one is assigned to this.doneEvent and thus gets set in the end.
|
||||
if(this.doneEvent == null) {
|
||||
|
||||
lock(this.syncRoot) {
|
||||
lock(this) {
|
||||
|
||||
if(this.doneEvent == null)
|
||||
this.doneEvent = new ManualResetEvent(this.ended);
|
||||
|
@ -124,20 +155,66 @@ namespace Nuclex.Support.Tracking {
|
|||
copy(this, eventArguments);
|
||||
}
|
||||
|
||||
#if PROGRESSION_STARTABLE
|
||||
/// <summary>Fires the AsyncStarted event</summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This event should be fired once when the implementing class begins its
|
||||
/// work to indicate any observers that the process is now running.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Calling this method is mandatory. Care should be taken that it is called
|
||||
/// exactly once and that it is called before OnAsyncEnded().
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
protected virtual void OnAsyncStarted() {
|
||||
|
||||
// Make sure that the progression is not started more than once.
|
||||
lock(this) {
|
||||
|
||||
// No double lock here as it would be an implementation fault if this exception
|
||||
// should be triggered. There's no sense in sacrificing normal runtime speed
|
||||
// for improved performance in a case that should never occur in the first place.
|
||||
if(this.started)
|
||||
throw new InvalidOperationException("The operation has already been started");
|
||||
|
||||
this.started = true;
|
||||
|
||||
}
|
||||
|
||||
// Fire the AsyncStarted event
|
||||
EventHandler copy = AsyncStarted;
|
||||
if(copy != null)
|
||||
copy(this, EventArgs.Empty);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>Fires the AsyncEnded event</summary>
|
||||
/// <remarks>
|
||||
/// This event should be fired by the implementing class when its work is completed.
|
||||
/// It's of no interest to this class whether the outcome of the process was successfull
|
||||
/// or not, the outcome and results of the process taking place need to be communicated
|
||||
/// seperately.
|
||||
/// <para>
|
||||
/// This event should be fired by the implementing class when its work is completed.
|
||||
/// It's of no interest to this class whether the outcome of the process was
|
||||
/// successfull or not, the outcome and results of the process taking place both
|
||||
/// need to be communicated seperately.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Calling this method is mandatory. Implementers need to take care that
|
||||
/// the OnAsyncEnded() method is called on any instance of Progression that's
|
||||
/// being created. This method also must not be called more than once.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
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
|
||||
// skip some safeguards against notifications arriving twice.
|
||||
lock(this.syncRoot) {
|
||||
lock(this) {
|
||||
|
||||
// No double lock here, this is an exception that indicates an implementation
|
||||
// error that will not be triggered under normal circumstances. We don't want
|
||||
// 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");
|
||||
|
||||
|
@ -158,14 +235,16 @@ namespace Nuclex.Support.Tracking {
|
|||
|
||||
}
|
||||
|
||||
/// <summary>Used to synchronize multithreaded accesses to this object</summary>
|
||||
private object syncRoot = new object();
|
||||
/// <summary>Event that will be set when the progression is completed</summary>
|
||||
/// <remarks>
|
||||
/// This event is will only be created when it is specifically asked for using
|
||||
/// the WaitHandle property.
|
||||
/// </remarks>
|
||||
private volatile ManualResetEvent doneEvent;
|
||||
#if PROGRESSION_STARTABLE
|
||||
/// <summary>Whether the operation has been started yet</summary>
|
||||
private volatile bool started;
|
||||
#endif
|
||||
/// <summary>Whether the operation has completed yet</summary>
|
||||
private volatile bool ended;
|
||||
|
||||
|
|
|
@ -1,3 +1,22 @@
|
|||
#region CPL License
|
||||
/*
|
||||
Nuclex Framework
|
||||
Copyright (C) 2002-2007 Nuclex Development Labs
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the IBM Common Public License as
|
||||
published by the IBM Corporation; either version 1.0 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
IBM Common Public License for more details.
|
||||
|
||||
You should have received a copy of the IBM Common Public
|
||||
License along with this library
|
||||
*/
|
||||
#endregion
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.Serialization;
|
||||
|
|
Loading…
Reference in New Issue
Block a user