'From Squeak6.0alpha of 12 May 2021 [latest update: #20523] on 17 May 2021 at 12:04:06 pm'!

!Dictionary methodsFor: 'accessing' stamp: 'ct 5/17/2021 12:03'!
at: key put: anObject during: aBlock

	| hasKey oldValue |
	self at: key ifPresent: [:value |
		(oldValue := value) == anObject ifTrue: [
			^ aBlock value].
		hasKey := true].
	self at: key put: anObject.
	
	^ aBlock ensure: [
		self at: key ifPresent: [:value | value == anObject ifTrue: [
			hasKey == true
				ifTrue: [self at: key put: oldValue]
				ifFalse: [self removeKey: key]]]]! !

!Dictionary methodsFor: 'accessing' stamp: 'ct 5/16/2021 20:54'!
removeKey: key during: aBlock

	| oldValue |
	oldValue := self
		removeKey: key
		ifAbsent: [^ aBlock value].
	
	^ aBlock ensure: [
		self at: key ifAbsentPut: [oldValue]]! !


!DictionaryTest methodsFor: 'tests - basic' stamp: 'ct 5/16/2021 20:47'!
testAtPutDuring

	| dictionary |
	dictionary := Dictionary new.
	
	"Change is present temporarily but reverted after aBlock"
	dictionary at: #a put: 1.
	dictionary at: #a put: 2 during: [
		self assert: 2 equals: (dictionary at: #a)].
	self assert: 1 equals: (dictionary at: #a).
	
	"Change is not reverted if overwritten during aBlock"
	dictionary at: #b put: 1.
	dictionary at: #b put: 2 during: [
		dictionary at: #b put: 3].
	self assert: 3 equals: (dictionary at: #b).
	
	"Different changes don't conflict"
	dictionary
		at: #a put: 1;
		at: #b put: 10.
	dictionary at: #b put: 11 during: [
		dictionary at: #a put: 2].
	self
		assert: 2 equals: (dictionary at: #a);
		assert: 10 equals: (dictionary at: #b).! !

!DictionaryTest methodsFor: 'tests - basic' stamp: 'ct 5/16/2021 20:53'!
testRemoveKeyDuring

	| dictionary |
	dictionary := Dictionary new
		at: #a put: 1;
		yourself.
	
	"Change is present temporarily but reverted after aBlock"
	dictionary removeKey: #a during: [
		self deny: (dictionary includesKey: #a)].
	self assert: 1 equals: (dictionary at: #a).
	
	"Change is not reverted if overwritten during aBlock"
	dictionary removeKey: #a during: [
		dictionary at: #a put: 3].
	self assert: 3 equals: (dictionary at: #a).
	
	"Different changes don't conflict"
	dictionary
		at: #a put: 1;
		at: #b put: 2.
	dictionary removeKey: #a during: [
		dictionary removeKey: #b].
	self
		assert: 1 equals: (dictionary at: #a);
		deny: (dictionary includesKey: #b).! !

