Added out-of-sync check for the Deque enumerator; added unit test for the out-of-sync check
git-svn-id: file:///srv/devel/repo-conversion/nusu@166 d2e56fa2-650e-0410-a79f-9358c0239efd
This commit is contained in:
parent
a56da772d4
commit
9ec6546f70
|
@ -38,6 +38,9 @@ namespace Nuclex.Support.Collections {
|
||||||
|
|
||||||
this.blocks[0][this.firstBlockStartIndex] = item;
|
this.blocks[0][this.firstBlockStartIndex] = item;
|
||||||
++this.count;
|
++this.count;
|
||||||
|
#if DEBUG
|
||||||
|
++this.version;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Appends an item to the end of the double-ended queue</summary>
|
/// <summary>Appends an item to the end of the double-ended queue</summary>
|
||||||
|
@ -52,6 +55,9 @@ namespace Nuclex.Support.Collections {
|
||||||
|
|
||||||
this.blocks[this.blocks.Count - 1][this.lastBlockEndIndex - 1] = item;
|
this.blocks[this.blocks.Count - 1][this.lastBlockEndIndex - 1] = item;
|
||||||
++this.count;
|
++this.count;
|
||||||
|
#if DEBUG
|
||||||
|
++this.version;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Inserts the item at the specified index</summary>
|
/// <summary>Inserts the item at the specified index</summary>
|
||||||
|
@ -64,6 +70,9 @@ namespace Nuclex.Support.Collections {
|
||||||
} else { // Nope, we're closer to the right end
|
} else { // Nope, we're closer to the right end
|
||||||
shiftRightAndInsert(index, item);
|
shiftRightAndInsert(index, item);
|
||||||
}
|
}
|
||||||
|
#if DEBUG
|
||||||
|
++this.version;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -54,6 +54,9 @@ namespace Nuclex.Support.Collections {
|
||||||
this.firstBlockStartIndex = 0;
|
this.firstBlockStartIndex = 0;
|
||||||
this.lastBlockEndIndex = 0;
|
this.lastBlockEndIndex = 0;
|
||||||
this.count = 0;
|
this.count = 0;
|
||||||
|
#if DEBUG
|
||||||
|
++this.version;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Removes the specified item from the deque</summary>
|
/// <summary>Removes the specified item from the deque</summary>
|
||||||
|
@ -66,6 +69,9 @@ namespace Nuclex.Support.Collections {
|
||||||
}
|
}
|
||||||
|
|
||||||
RemoveAt(index);
|
RemoveAt(index);
|
||||||
|
#if DEBUG
|
||||||
|
++this.version;
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,6 +98,9 @@ namespace Nuclex.Support.Collections {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
--this.count;
|
--this.count;
|
||||||
|
#if DEBUG
|
||||||
|
++this.version;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Removes the last item in the double-ended queue</summary>
|
/// <summary>Removes the last item in the double-ended queue</summary>
|
||||||
|
@ -118,6 +127,9 @@ namespace Nuclex.Support.Collections {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
--this.count;
|
--this.count;
|
||||||
|
#if DEBUG
|
||||||
|
++this.version;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Removes the item at the specified index</summary>
|
/// <summary>Removes the item at the specified index</summary>
|
||||||
|
@ -129,6 +141,9 @@ namespace Nuclex.Support.Collections {
|
||||||
} else { // Nope, we're closer to the right end
|
} else { // Nope, we're closer to the right end
|
||||||
removeFromRight(index);
|
removeFromRight(index);
|
||||||
}
|
}
|
||||||
|
#if DEBUG
|
||||||
|
++this.version;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -93,7 +93,6 @@ namespace Nuclex.Support.Collections {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>Verifies that the Insert() method works in all cases</summary>
|
/// <summary>Verifies that the Insert() method works in all cases</summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// We have several different cases here that will be tested. The deque can
|
/// We have several different cases here that will be tested. The deque can
|
||||||
|
@ -655,6 +654,23 @@ namespace Nuclex.Support.Collections {
|
||||||
delegate() { intDeque.CopyTo(new int[7], 0); }
|
delegate() { intDeque.CopyTo(new int[7], 0); }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
/// <summary>
|
||||||
|
/// Tests whether the deque enumerator detects when it runs out of sync
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestInvalidatedEnumeratorDetection() {
|
||||||
|
Deque<int> intDeque = createDeque(8);
|
||||||
|
using(IEnumerator<int> enumerator = intDeque.GetEnumerator()) {
|
||||||
|
Assert.IsTrue(enumerator.MoveNext());
|
||||||
|
intDeque.AddFirst(12345);
|
||||||
|
Assert.Throws<InvalidOperationException>(
|
||||||
|
delegate() { enumerator.MoveNext(); }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a deque whose first element does not coincide with a block boundary
|
/// Creates a deque whose first element does not coincide with a block boundary
|
||||||
|
|
|
@ -65,6 +65,9 @@ namespace Nuclex.Support.Collections {
|
||||||
/// <summary>The item at the enumerator's current position</summary>
|
/// <summary>The item at the enumerator's current position</summary>
|
||||||
public ItemType Current {
|
public ItemType Current {
|
||||||
get {
|
get {
|
||||||
|
#if DEBUG
|
||||||
|
checkVersion();
|
||||||
|
#endif
|
||||||
if(this.currentBlock == null) {
|
if(this.currentBlock == null) {
|
||||||
throw new InvalidOperationException("Enumerator is not on a valid position");
|
throw new InvalidOperationException("Enumerator is not on a valid position");
|
||||||
}
|
}
|
||||||
|
@ -77,6 +80,10 @@ namespace Nuclex.Support.Collections {
|
||||||
/// <returns>True if there was a next item</returns>
|
/// <returns>True if there was a next item</returns>
|
||||||
public bool MoveNext() {
|
public bool MoveNext() {
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
checkVersion();
|
||||||
|
#endif
|
||||||
|
|
||||||
// If we haven't reached the last block yet
|
// If we haven't reached the last block yet
|
||||||
if(this.currentBlockIndex < this.lastBlock) {
|
if(this.currentBlockIndex < this.lastBlock) {
|
||||||
|
|
||||||
|
@ -117,6 +124,7 @@ namespace Nuclex.Support.Collections {
|
||||||
this.currentBlock = null;
|
this.currentBlock = null;
|
||||||
this.currentBlockIndex = -1;
|
this.currentBlockIndex = -1;
|
||||||
this.subIndex = this.deque.blockSize - 1;
|
this.subIndex = this.deque.blockSize - 1;
|
||||||
|
this.expectedVersion = this.deque.version;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>The item at the enumerator's current position</summary>
|
/// <summary>The item at the enumerator's current position</summary>
|
||||||
|
@ -124,6 +132,14 @@ namespace Nuclex.Support.Collections {
|
||||||
get { return Current; }
|
get { return Current; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
/// <summary>Ensures that the deque has not changed</summary>
|
||||||
|
private void checkVersion() {
|
||||||
|
if(this.expectedVersion != this.deque.version)
|
||||||
|
throw new InvalidOperationException("Deque has been modified");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/// <summary>Deque the enumerator belongs to</summary>
|
/// <summary>Deque the enumerator belongs to</summary>
|
||||||
private Deque<ItemType> deque;
|
private Deque<ItemType> deque;
|
||||||
/// <summary>Size of the blocks in the deque</summary>
|
/// <summary>Size of the blocks in the deque</summary>
|
||||||
|
@ -140,6 +156,9 @@ namespace Nuclex.Support.Collections {
|
||||||
/// <summary>Index in the current block</summary>
|
/// <summary>Index in the current block</summary>
|
||||||
private int subIndex;
|
private int subIndex;
|
||||||
|
|
||||||
|
/// <summary>Version the deque is expected to have</summary>
|
||||||
|
private int expectedVersion;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion // class Enumerator
|
#endregion // class Enumerator
|
||||||
|
@ -303,6 +322,10 @@ namespace Nuclex.Support.Collections {
|
||||||
private int firstBlockStartIndex;
|
private int firstBlockStartIndex;
|
||||||
/// <summary>End index of data in the last block</summary>
|
/// <summary>End index of data in the last block</summary>
|
||||||
private int lastBlockEndIndex;
|
private int lastBlockEndIndex;
|
||||||
|
#if DEBUG
|
||||||
|
/// <summary>Used to detect when enumerators go out of sync</summary>
|
||||||
|
private int version;
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ namespace Nuclex.Support.Collections {
|
||||||
public void Reset() {
|
public void Reset() {
|
||||||
this.index = -1;
|
this.index = -1;
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
this.expectedVersion = priorityQueue.version;
|
this.expectedVersion = this.priorityQueue.version;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user