浏览代码

(Debug) Assertion on modification during iteration.

woollybah 10 年之前
父节点
当前提交
333cd0a213
共有 3 个文件被更改,包括 79 次插入8 次删除
  1. 26 2
      map.mod/intmap.bmx
  2. 27 4
      map.mod/map.bmx
  3. 26 2
      map.mod/ptrmap.bmx

+ 26 - 2
map.mod/intmap.bmx

@@ -23,6 +23,9 @@ Type TIntMap
 	End Method
 
 	Method Clear()
+		If Not IsEmpty() Then
+			_modCount :+ 1
+		End If
 		bmx_map_intmap_clear(Varptr _root)
 	End Method
 	
@@ -32,6 +35,7 @@ Type TIntMap
 	
 	Method Insert( key:Int,value:Object )
 		bmx_map_intmap_insert(key, value, Varptr _root)
+		_modCount :+ 1
 	End Method
 
 	Method Contains:Int( key:Int )
@@ -43,6 +47,7 @@ Type TIntMap
 	End Method
 	
 	Method Remove( key:Int )
+		_modCount :+ 1
 		Return bmx_map_intmap_remove(key, Varptr _root)
 	End Method
 
@@ -66,6 +71,8 @@ Type TIntMap
 		End If
 		Local mapenum:TIntMapEnumerator=New TIntMapEnumerator
 		mapenum._enumerator=nodeenum
+		nodeenum._map = Self
+		nodeenum._expectedModCount = _modCount
 		Return mapenum
 	End Method
 	
@@ -79,6 +86,8 @@ Type TIntMap
 		End If
 		Local mapenum:TIntMapEnumerator=New TIntMapEnumerator
 		mapenum._enumerator=nodeenum
+		nodeenum._map = Self
+		nodeenum._expectedModCount = _modCount
 		Return mapenum
 	End Method
 	
@@ -91,11 +100,15 @@ Type TIntMap
 	Method ObjectEnumerator:TIntNodeEnumerator()
 		Local nodeenum:TIntNodeEnumerator=New TIntNodeEnumerator
 		nodeenum._node=_FirstNode()
+		nodeenum._map = Self
+		nodeenum._expectedModCount = _modCount
 		Return nodeenum
 	End Method
 
 	Field _root:Byte Ptr
-	
+
+	Field _modCount:Int
+
 End Type
 
 Type TIntNode
@@ -135,10 +148,15 @@ End Type
 
 Type TIntNodeEnumerator
 	Method HasNext()
-		Return _node.HasNext()
+		Local has:Int = _node.HasNext()
+		If Not has Then
+			_map = Null
+		End If
+		Return has
 	End Method
 	
 	Method NextObject:Object()
+		Assert _expectedModCount = _map._modCount, "TIntMap Concurrent Modification"
 		Local node:TIntNode=_node
 		_node=_node.NextNode()
 		Return node
@@ -147,11 +165,15 @@ Type TIntNodeEnumerator
 	'***** PRIVATE *****
 		
 	Field _node:TIntNode	
+
+	Field _map:TIntMap
+	Field _expectedModCount:Int
 End Type
 
 Type TIntKeyEnumerator Extends TIntNodeEnumerator
 	Field _key:TIntKey = New TIntKey
 	Method NextObject:Object()
+		Assert _expectedModCount = _map._modCount, "TIntMap Concurrent Modification"
 		Local node:TIntNode=_node
 		_node=_node.NextNode()
 		_key.value = node.Key()
@@ -161,6 +183,7 @@ End Type
 
 Type TIntValueEnumerator Extends TIntNodeEnumerator
 	Method NextObject:Object()
+		Assert _expectedModCount = _map._modCount, "TIntMap Concurrent Modification"
 		Local node:TIntNode=_node
 		_node=_node.NextNode()
 		Return node.Value()
@@ -176,6 +199,7 @@ End Type
 
 Type TIntEmptyEnumerator Extends TIntNodeEnumerator
 	Method HasNext()
+		_map = Null
 		Return False
 	End Method
 End Type

+ 27 - 4
map.mod/map.bmx

@@ -6,12 +6,14 @@ bbdoc: Data structures/Maps
 End Rem
 Module BRL.Map
 
-ModuleInfo "Version: 1.07"
+ModuleInfo "Version: 1.08"
 ModuleInfo "Author: Mark Sibly"
 ModuleInfo "License: zlib/libpng"
 ModuleInfo "Copyright: Blitz Research Ltd"
 ModuleInfo "Modserver: BRL"
 
+ModuleInfo "History: 1.08"
+ModuleInfo "History: (Debug) Assertion on modification during iteration."
 ModuleInfo "History: 1.07 Release"
 ModuleInfo "History: Fixed MapKeys/MapValues functions to return enumerators"
 ModuleInfo "History: 1.06 Release"
@@ -126,10 +128,15 @@ End Type
 
 Type TNodeEnumerator
 	Method HasNext()
-		Return _node<>nil
+		Local has:Int = _node<>nil
+		If Not has Then
+			_map = Null
+		End If
+		Return has
 	End Method
 	
 	Method NextObject:Object()
+		Assert _expectedModCount = _map._modCount, "TMap Concurrent Modification"
 		Local node:TNode=_node
 		_node=_node.NextNode()
 		Return node
@@ -137,11 +144,15 @@ Type TNodeEnumerator
 
 	'***** PRIVATE *****
 		
-	Field _node:TNode	
+	Field _node:TNode
+	
+	Field _map:TMap
+	Field _expectedModCount:Int
 End Type
 
 Type TKeyEnumerator Extends TNodeEnumerator
 	Method NextObject:Object()
+		Assert _expectedModCount = _map._modCount, "TMap Concurrent Modification"
 		Local node:TNode=_node
 		_node=_node.NextNode()
 		Return node._key
@@ -150,6 +161,7 @@ End Type
 
 Type TValueEnumerator Extends TNodeEnumerator
 	Method NextObject:Object()
+		Assert _expectedModCount = _map._modCount, "TMap Concurrent Modification"
 		Local node:TNode=_node
 		_node=_node.NextNode()
 		Return node._value
@@ -176,6 +188,7 @@ Type TMap
 		If _root=nil Return
 		_root.Clear
 		_root=nil
+		_modCount :+ 1
 	End Method
 	
 	Method IsEmpty()
@@ -206,6 +219,8 @@ Type TMap
 		node._value=value
 		node._color=RED
 		node._parent=parent
+
+		_modCount :+ 1
 		
 		If parent=nil
 			_root=node
@@ -233,6 +248,7 @@ Type TMap
 		Local node:TNode=_FindNode( key )
 		If node=nil Return 0
 		 _RemoveNode node
+		_modCount :+ 1
 		Return 1
 	End Method
 	
@@ -241,6 +257,8 @@ Type TMap
 		nodeenum._node=_FirstNode()
 		Local mapenum:TMapEnumerator=New TMapEnumerator
 		mapenum._enumerator=nodeenum
+		nodeenum._map = Self
+		nodeenum._expectedModCount = _modCount
 		Return mapenum
 	End Method
 	
@@ -249,6 +267,8 @@ Type TMap
 		nodeenum._node=_FirstNode()
 		Local mapenum:TMapEnumerator=New TMapEnumerator
 		mapenum._enumerator=nodeenum
+		nodeenum._map = Self
+		nodeenum._expectedModCount = _modCount
 		Return mapenum
 	End Method
 	
@@ -257,10 +277,12 @@ Type TMap
 		map._root=_root.Copy( nil )
 		Return map
 	End Method
-	
+
 	Method ObjectEnumerator:TNodeEnumerator()
 		Local nodeenum:TNodeEnumerator=New TNodeEnumerator
 		nodeenum._node=_FirstNode()
+		nodeenum._map = Self
+		nodeenum._expectedModCount = _modCount
 		Return nodeenum
 	End Method
 	
@@ -478,6 +500,7 @@ Type TMap
 	
 	Field _root:TNode=nil
 	
+	Field _modCount:Int
 End Type
 
 Rem

+ 26 - 2
map.mod/ptrmap.bmx

@@ -23,6 +23,9 @@ Type TPtrMap
 	End Method
 
 	Method Clear()
+		If Not IsEmpty() Then
+			_modCount :+ 1
+		End If
 		bmx_map_ptrmap_clear(Varptr _root)
 	End Method
 	
@@ -32,6 +35,7 @@ Type TPtrMap
 	
 	Method Insert( key:Byte Ptr,value:Object )
 		bmx_map_ptrmap_insert(key, value, Varptr _root)
+		_modCount :+ 1
 	End Method
 
 	Method Contains:Int( key:Byte Ptr )
@@ -43,6 +47,7 @@ Type TPtrMap
 	End Method
 	
 	Method Remove( key:Byte Ptr )
+		_modCount :+ 1
 		Return bmx_map_ptrmap_remove(key, Varptr _root)
 	End Method
 
@@ -66,6 +71,8 @@ Type TPtrMap
 		End If
 		Local mapenum:TPtrMapEnumerator=New TPtrMapEnumerator
 		mapenum._enumerator=nodeenum
+		nodeenum._map = Self
+		nodeenum._expectedModCount = _modCount
 		Return mapenum
 	End Method
 	
@@ -79,6 +86,8 @@ Type TPtrMap
 		End If
 		Local mapenum:TPtrMapEnumerator=New TPtrMapEnumerator
 		mapenum._enumerator=nodeenum
+		nodeenum._map = Self
+		nodeenum._expectedModCount = _modCount
 		Return mapenum
 	End Method
 	
@@ -91,11 +100,15 @@ Type TPtrMap
 	Method ObjectEnumerator:TPtrNodeEnumerator()
 		Local nodeenum:TPtrNodeEnumerator=New TPtrNodeEnumerator
 		nodeenum._node=_FirstNode()
+		nodeenum._map = Self
+		nodeenum._expectedModCount = _modCount
 		Return nodeenum
 	End Method
 
 	Field _root:Byte Ptr
 	
+	Field _modCount:Int
+	
 End Type
 
 Type TPtrNode
@@ -127,7 +140,7 @@ Type TPtrNode
 End Type
 
 Rem
-bbdoc: Byte Ptr holder for key returned by TIntMap.Keys() enumerator.
+bbdoc: Byte Ptr holder for key returned by TPtrMap.Keys() enumerator.
 End Rem
 Type TPtrKey
 	Field value:Byte Ptr
@@ -135,10 +148,15 @@ End Type
 
 Type TPtrNodeEnumerator
 	Method HasNext()
-		Return _node.HasNext()
+		Local has:Int = _node.HasNext()
+		If Not has Then
+			_map = Null
+		End If
+		Return has
 	End Method
 	
 	Method NextObject:Object()
+		Assert _expectedModCount = _map._modCount, "TPtrMap Concurrent Modification"
 		Local node:TPtrNode=_node
 		_node=_node.NextNode()
 		Return node
@@ -147,11 +165,15 @@ Type TPtrNodeEnumerator
 	'***** PRIVATE *****
 		
 	Field _node:TPtrNode	
+
+	Field _map:TPtrMap
+	Field _expectedModCount:Int
 End Type
 
 Type TPtrKeyEnumerator Extends TPtrNodeEnumerator
 	Field _key:TPtrKey = New TPtrKey
 	Method NextObject:Object()
+		Assert _expectedModCount = _map._modCount, "TPtrMap Concurrent Modification"
 		Local node:TPtrNode=_node
 		_node=_node.NextNode()
 		_key.value = node.Key()
@@ -161,6 +183,7 @@ End Type
 
 Type TPtrValueEnumerator Extends TPtrNodeEnumerator
 	Method NextObject:Object()
+		Assert _expectedModCount = _map._modCount, "TPtrMap Concurrent Modification"
 		Local node:TPtrNode=_node
 		_node=_node.NextNode()
 		Return node.Value()
@@ -176,6 +199,7 @@ End Type
 
 Type TPtrEmptyEnumerator Extends TPtrNodeEnumerator
 	Method HasNext()
+		_map = Null
 		Return False
 	End Method
 End Type