@@ -31,17 +31,6 @@ internal class TrieNode<E>(var bitmap: Int,
31
31
32
32
constructor (bitmap: Int , buffer: Array <Any ?>) : this (bitmap, buffer, null )
33
33
34
- fun makeMutableFor (mutator : PersistentHashSetBuilder <* >): TrieNode <E > {
35
- if (marker == = mutator.marker) { return this }
36
- return TrieNode (bitmap, buffer.copyOf(), mutator.marker)
37
- }
38
-
39
- private fun ensureMutableBy (mutator : PersistentHashSetBuilder <* >) {
40
- if (marker != = mutator.marker) {
41
- throw IllegalStateException (" Markers expected to be same" )
42
- }
43
- }
44
-
45
34
private fun isNullCellAt (position : Int ): Boolean {
46
35
return bitmap and position == 0
47
36
}
@@ -74,12 +63,17 @@ internal class TrieNode<E>(var bitmap: Int,
74
63
return TrieNode (bitmap or position, newBuffer)
75
64
}
76
65
77
- private fun mutableAddElementAt (position : Int , element : E ) {
66
+ private fun mutableAddElementAt (position : Int , element : E , mutatorMarker : Marker ): TrieNode < E > {
78
67
// assert(isNullCellAt(position))
79
68
80
69
val index = indexOfCellAt(position)
81
- buffer = bufferAddElementAtIndex(index, element)
82
- bitmap = bitmap or position
70
+ if (marker == = mutatorMarker) {
71
+ buffer = bufferAddElementAtIndex(index, element)
72
+ bitmap = bitmap or position
73
+ return this
74
+ }
75
+ val newBuffer = bufferAddElementAtIndex(index, element)
76
+ return TrieNode (bitmap or position, newBuffer, mutatorMarker)
83
77
}
84
78
85
79
private fun updateNodeAtIndex (nodeIndex : Int , newNode : TrieNode <E >): TrieNode <E > {
@@ -90,8 +84,16 @@ internal class TrieNode<E>(var bitmap: Int,
90
84
return TrieNode (bitmap, newBuffer)
91
85
}
92
86
93
- private fun mutableUpdateNodeAtIndex (nodeIndex : Int , newNode : TrieNode <E >) {
94
- buffer[nodeIndex] = newNode
87
+ private fun mutableUpdateNodeAtIndex (nodeIndex : Int , newNode : TrieNode <E >, mutatorMarker : Marker ): TrieNode <E > {
88
+ // assert(buffer[nodeIndex] !== newNode)
89
+
90
+ if (marker == = mutatorMarker) {
91
+ buffer[nodeIndex] = newNode
92
+ return this
93
+ }
94
+ val newBuffer = buffer.copyOf()
95
+ newBuffer[nodeIndex] = newNode
96
+ return TrieNode (bitmap, newBuffer, mutatorMarker)
95
97
}
96
98
97
99
private fun makeNodeAtIndex (elementIndex : Int , newElementHash : Int , newElement : E ,
@@ -112,10 +114,16 @@ internal class TrieNode<E>(var bitmap: Int,
112
114
}
113
115
114
116
private fun mutableMoveElementToNode (elementIndex : Int , newElementHash : Int , newElement : E ,
115
- shift : Int , mutator : PersistentHashSetBuilder < * >) {
117
+ shift : Int , mutatorMarker : Marker ): TrieNode < E > {
116
118
// assert(!isNullCellAt(position))
117
119
118
- buffer[elementIndex] = makeNodeAtIndex(elementIndex, newElementHash, newElement, shift, mutator.marker)
120
+ if (marker == = mutatorMarker) {
121
+ buffer[elementIndex] = makeNodeAtIndex(elementIndex, newElementHash, newElement, shift, mutatorMarker)
122
+ return this
123
+ }
124
+ val newBuffer = buffer.copyOf()
125
+ newBuffer[elementIndex] = makeNodeAtIndex(elementIndex, newElementHash, newElement, shift, mutatorMarker)
126
+ return TrieNode (bitmap, newBuffer, mutatorMarker)
119
127
}
120
128
121
129
private fun makeNode (elementHash1 : Int , element1 : E , elementHash2 : Int , element2 : E ,
@@ -155,10 +163,17 @@ internal class TrieNode<E>(var bitmap: Int,
155
163
return TrieNode (bitmap xor position, newBuffer)
156
164
}
157
165
158
- private fun mutableRemoveCellAtIndex (cellIndex : Int , position : Int ) {
166
+ private fun mutableRemoveCellAtIndex (cellIndex : Int , position : Int , mutatorMarker : Marker ): TrieNode < E > ? {
159
167
// assert(!isNullCellAt(position))
160
- buffer = bufferRemoveCellAtIndex(cellIndex)
161
- bitmap = bitmap xor position
168
+ if (buffer.size == 1 ) { return null }
169
+
170
+ if (marker == = mutatorMarker) {
171
+ buffer = bufferRemoveCellAtIndex(cellIndex)
172
+ bitmap = bitmap xor position
173
+ return this
174
+ }
175
+ val newBuffer = bufferRemoveCellAtIndex(cellIndex)
176
+ return TrieNode (bitmap xor position, newBuffer, mutatorMarker)
162
177
}
163
178
164
179
private fun collisionRemoveElementAtIndex (i : Int ): TrieNode <E >? {
@@ -168,8 +183,15 @@ internal class TrieNode<E>(var bitmap: Int,
168
183
return TrieNode (0 , newBuffer)
169
184
}
170
185
171
- private fun mutableCollisionRemoveElementAtIndex (i : Int ) {
172
- buffer = bufferRemoveCellAtIndex(i)
186
+ private fun mutableCollisionRemoveElementAtIndex (i : Int , mutatorMarker : Marker ): TrieNode <E >? {
187
+ if (buffer.size == 1 ) { return null }
188
+
189
+ if (marker == = mutatorMarker) {
190
+ buffer = bufferRemoveCellAtIndex(i)
191
+ return this
192
+ }
193
+ val newBuffer = bufferRemoveCellAtIndex(i)
194
+ return TrieNode (0 , newBuffer, mutatorMarker)
173
195
}
174
196
175
197
private fun collisionContainsElement (element : E ): Boolean {
@@ -182,11 +204,15 @@ internal class TrieNode<E>(var bitmap: Int,
182
204
return TrieNode (0 , newBuffer)
183
205
}
184
206
185
- private fun mutableCollisionAdd (element : E , mutator : PersistentHashSetBuilder <* >): Boolean {
186
- if (collisionContainsElement(element)) { return false }
207
+ private fun mutableCollisionAdd (element : E , mutator : PersistentHashSetBuilder <* >): TrieNode < E > {
208
+ if (collisionContainsElement(element)) { return this }
187
209
mutator.size++
188
- buffer = bufferAddElementAtIndex(0 , element)
189
- return true
210
+ if (marker == = mutator.marker) {
211
+ buffer = bufferAddElementAtIndex(0 , element)
212
+ return this
213
+ }
214
+ val newBuffer = bufferAddElementAtIndex(0 , element)
215
+ return TrieNode (0 , newBuffer, mutator.marker)
190
216
}
191
217
192
218
private fun collisionRemove (element : E ): TrieNode <E >? {
@@ -197,14 +223,13 @@ internal class TrieNode<E>(var bitmap: Int,
197
223
return this
198
224
}
199
225
200
- private fun mutableCollisionRemove (element : E , mutator : PersistentHashSetBuilder <* >): Boolean {
226
+ private fun mutableCollisionRemove (element : E , mutator : PersistentHashSetBuilder <* >): TrieNode < E > ? {
201
227
val index = buffer.indexOf(element)
202
228
if (index != - 1 ) {
203
229
mutator.size--
204
- mutableCollisionRemoveElementAtIndex(index)
205
- return true
230
+ return mutableCollisionRemoveElementAtIndex(index, mutator.marker)
206
231
}
207
- return false
232
+ return this
208
233
}
209
234
210
235
fun contains (elementHash : Int , element : E , shift : Int ): Boolean {
@@ -249,31 +274,29 @@ internal class TrieNode<E>(var bitmap: Int,
249
274
return moveElementToNode(cellIndex, elementHash, element, shift)
250
275
}
251
276
252
- fun mutableAdd (elementHash : Int , element : E , shift : Int , mutator : PersistentHashSetBuilder <* >): Boolean {
253
- ensureMutableBy(mutator)
277
+ fun mutableAdd (elementHash : Int , element : E , shift : Int , mutator : PersistentHashSetBuilder <* >): TrieNode <E > {
254
278
val cellPosition = 1 shl ((elementHash shr shift) and MAX_BRANCHING_FACTOR_MINUS_ONE )
255
279
256
280
if (isNullCellAt(cellPosition)) { // element is absent
257
281
mutator.size++
258
- mutableAddElementAt(cellPosition, element)
259
- return true
282
+ return mutableAddElementAt(cellPosition, element, mutator.marker)
260
283
}
261
284
262
285
val cellIndex = indexOfCellAt(cellPosition)
263
286
if (buffer[cellIndex] is TrieNode <* >) { // element may be in node
264
- val targetNode = nodeAtIndex(cellIndex).makeMutableFor(mutator)
265
- mutableUpdateNodeAtIndex(cellIndex, targetNode)
266
- return if (shift == MAX_SHIFT ) {
287
+ val targetNode = nodeAtIndex(cellIndex)
288
+ val newNode = if (shift == MAX_SHIFT ) {
267
289
targetNode.mutableCollisionAdd(element, mutator)
268
290
} else {
269
291
targetNode.mutableAdd(elementHash, element, shift + LOG_MAX_BRANCHING_FACTOR , mutator)
270
292
}
293
+ if (targetNode == = newNode) { return this }
294
+ return mutableUpdateNodeAtIndex(cellIndex, newNode, mutator.marker)
271
295
}
272
296
// element is directly in buffer
273
- if (element == buffer[cellIndex]) { return false }
297
+ if (element == buffer[cellIndex]) { return this }
274
298
mutator.size++
275
- mutableMoveElementToNode(cellIndex, elementHash, element, shift, mutator)
276
- return true
299
+ return mutableMoveElementToNode(cellIndex, elementHash, element, shift, mutator.marker)
277
300
}
278
301
279
302
fun remove (elementHash : Int , element : E , shift : Int ): TrieNode <E >? {
@@ -302,33 +325,31 @@ internal class TrieNode<E>(var bitmap: Int,
302
325
return this
303
326
}
304
327
305
- fun mutableRemove (elementHash : Int , element : E , shift : Int , mutator : PersistentHashSetBuilder <* >): Boolean {
306
- ensureMutableBy(mutator)
328
+ fun mutableRemove (elementHash : Int , element : E , shift : Int , mutator : PersistentHashSetBuilder <* >): TrieNode <E >? {
307
329
val cellPosition = 1 shl ((elementHash shr shift) and MAX_BRANCHING_FACTOR_MINUS_ONE )
308
330
309
331
if (isNullCellAt(cellPosition)) { // element is absent
310
- return false
332
+ return this
311
333
}
312
334
313
335
val cellIndex = indexOfCellAt(cellPosition)
314
336
if (buffer[cellIndex] is TrieNode <* >) { // element may be in node
315
- val targetNode = nodeAtIndex(cellIndex).makeMutableFor(mutator)
316
- mutableUpdateNodeAtIndex(cellIndex, targetNode)
317
- val result = if (shift == MAX_SHIFT ) {
337
+ val targetNode = nodeAtIndex(cellIndex)
338
+ val newNode = if (shift == MAX_SHIFT ) {
318
339
targetNode.mutableCollisionRemove(element, mutator)
319
340
} else {
320
341
targetNode.mutableRemove(elementHash, element, shift + LOG_MAX_BRANCHING_FACTOR , mutator)
321
342
}
322
- if (targetNode.buffer.isEmpty()) { mutableRemoveCellAtIndex(cellIndex, cellPosition) }
323
- return result
343
+ if (targetNode == = newNode) { return this }
344
+ if (newNode == null ) { return mutableRemoveCellAtIndex(cellIndex, cellPosition, mutator.marker) }
345
+ return mutableUpdateNodeAtIndex(cellIndex, newNode, mutator.marker)
324
346
}
325
347
// element is directly in buffer
326
348
if (element == buffer[cellIndex]) {
327
349
mutator.size--
328
- mutableRemoveCellAtIndex(cellIndex, cellPosition) // check is empty
329
- return true
350
+ return mutableRemoveCellAtIndex(cellIndex, cellPosition, mutator.marker) // check is empty
330
351
}
331
- return false
352
+ return this
332
353
}
333
354
334
355
internal companion object {
0 commit comments