@@ -75,6 +75,14 @@ internal class TrieNode<K, V>(
75
75
) {
76
76
constructor (dataMap: Int , nodeMap: Int , buffer: Array <Any ?>) : this (dataMap, nodeMap, buffer, null )
77
77
78
+ internal class ModificationResult <K , V >(var node : TrieNode <K , V >, val sizeDelta : Int ) {
79
+ inline fun replaceNode (operation : (TrieNode <K , V >) -> TrieNode <K , V >): ModificationResult <K , V > =
80
+ apply { node = operation(node) }
81
+ }
82
+
83
+ private fun asInsertResult () = ModificationResult (this , 1 )
84
+ private fun asUpdateResult () = ModificationResult (this , 0 )
85
+
78
86
internal var buffer: Array <Any ?> = buffer
79
87
private set
80
88
@@ -333,21 +341,19 @@ internal class TrieNode<K, V>(
333
341
return null
334
342
}
335
343
336
- private fun collisionPut (key : K , value : V , modification : ModificationWrapper ): TrieNode <K , V > {
344
+ private fun collisionPut (key : K , value : V ): ModificationResult <K , V >? {
337
345
for (i in 0 until buffer.size step ENTRY_SIZE ) {
338
346
if (key == buffer[i]) {
339
347
if (value == = buffer[i + 1 ]) {
340
- return this
348
+ return null
341
349
}
342
- modification.value = UPDATE_VALUE
343
350
val newBuffer = buffer.copyOf()
344
351
newBuffer[i + 1 ] = value
345
- return TrieNode (0 , 0 , newBuffer)
352
+ return TrieNode < K , V > (0 , 0 , newBuffer).asUpdateResult( )
346
353
}
347
354
}
348
- modification.value = PUT_KEY_VALUE
349
355
val newBuffer = buffer.insertEntryAtIndex(0 , key, value)
350
- return TrieNode (0 , 0 , newBuffer)
356
+ return TrieNode < K , V > (0 , 0 , newBuffer).asInsertResult( )
351
357
}
352
358
353
359
private fun mutableCollisionPut (key : K , value : V , mutator : PersistentHashMapBuilder <K , V >): TrieNode <K , V > {
@@ -454,37 +460,33 @@ internal class TrieNode<K, V>(
454
460
return null
455
461
}
456
462
457
- fun put (keyHash : Int , key : K , value : @UnsafeVariance V , shift : Int , modification : ModificationWrapper ): TrieNode <K , V > {
463
+ fun put (keyHash : Int , key : K , value : @UnsafeVariance V , shift : Int ): ModificationResult <K , V >? {
458
464
val keyPositionMask = 1 shl indexSegment(keyHash, shift)
459
465
460
466
if (hasEntryAt(keyPositionMask)) { // key is directly in buffer
461
467
val keyIndex = entryKeyIndex(keyPositionMask)
462
468
463
469
if (key == keyAtIndex(keyIndex)) {
464
- modification.value = UPDATE_VALUE
465
- if (valueAtKeyIndex(keyIndex) == = value) return this
470
+ if (valueAtKeyIndex(keyIndex) == = value) return null
466
471
467
- return updateValueAtIndex(keyIndex, value)
472
+ return updateValueAtIndex(keyIndex, value).asUpdateResult()
468
473
}
469
- modification.value = PUT_KEY_VALUE
470
- return moveEntryToNode(keyIndex, keyPositionMask, keyHash, key, value, shift)
474
+ return moveEntryToNode(keyIndex, keyPositionMask, keyHash, key, value, shift).asInsertResult()
471
475
}
472
476
if (hasNodeAt(keyPositionMask)) { // key is in node
473
477
val nodeIndex = nodeIndex(keyPositionMask)
474
478
475
479
val targetNode = nodeAtIndex(nodeIndex)
476
- val newNode = if (shift == MAX_SHIFT ) {
477
- targetNode.collisionPut(key, value, modification)
480
+ val putResult = if (shift == MAX_SHIFT ) {
481
+ targetNode.collisionPut(key, value) ? : return null
478
482
} else {
479
- targetNode.put(keyHash, key, value, shift + LOG_MAX_BRANCHING_FACTOR , modification)
483
+ targetNode.put(keyHash, key, value, shift + LOG_MAX_BRANCHING_FACTOR ) ? : return null
480
484
}
481
- if (targetNode == = newNode) return this
482
- return updateNodeAtIndex(nodeIndex, newNode)
485
+ return putResult.replaceNode { node -> updateNodeAtIndex(nodeIndex, node) }
483
486
}
484
487
485
488
// no entry at this key hash segment
486
- modification.value = PUT_KEY_VALUE
487
- return insertEntryAt(keyPositionMask, key, value)
489
+ return insertEntryAt(keyPositionMask, key, value).asInsertResult()
488
490
}
489
491
490
492
fun mutablePut (keyHash : Int , key : K , value : @UnsafeVariance V , shift : Int , mutator : PersistentHashMapBuilder <K , V >): TrieNode <K , V > {
0 commit comments