@@ -61,29 +61,32 @@ internal class TestMainDispatcher(delegate: CoroutineDispatcher):
61
61
* next modification.
62
62
*/
63
63
private class NonConcurrentlyModifiable <T >(initialValue : T , private val name : String ) {
64
+ private val reader: AtomicRef <Throwable ?> = atomic(null ) // last reader to attempt access
64
65
private val readers = atomic(0 ) // number of concurrent readers
65
- private val isWriting = atomic(false ) // a modification is happening currently
66
+ private val writer : AtomicRef < Throwable ?> = atomic(null ) // writer currently performing value modification
66
67
private val exceptionWhenReading: AtomicRef <Throwable ?> = atomic(null ) // exception from reading
67
68
private val _value = atomic(initialValue) // the backing field for the value
68
69
69
- private fun concurrentWW () = IllegalStateException (" $name is modified concurrently" )
70
- private fun concurrentRW () = IllegalStateException (" $name is used concurrently with setting it" )
70
+ private fun concurrentWW (location : Throwable ) = IllegalStateException (" $name is modified concurrently" , location )
71
+ private fun concurrentRW (location : Throwable ) = IllegalStateException (" $name is used concurrently with setting it" , location )
71
72
72
73
var value: T
73
74
get() {
75
+ reader.getAndSet(Throwable (" reader location" ))
74
76
readers.incrementAndGet()
75
- if (isWriting .value) exceptionWhenReading.value = concurrentRW()
77
+ writer .value?. let { exceptionWhenReading.value = concurrentRW(it) }
76
78
val result = _value .value
77
79
readers.decrementAndGet()
78
80
return result
79
81
}
80
82
set(value) {
81
83
exceptionWhenReading.getAndSet(null )?.let { throw it }
82
- if (readers.value != 0 ) throw concurrentRW()
83
- if (! isWriting.compareAndSet(expect = false , update = true )) throw concurrentWW()
84
+ if (readers.value != 0 ) reader.value?.let { throw concurrentRW(it) }
85
+ val writerLocation = Throwable ()
86
+ writer.getAndSet(writerLocation)?.let { throw concurrentWW(it) }
84
87
_value .value = value
85
- isWriting.value = false
86
- if (readers.value != 0 ) throw concurrentRW()
88
+ writer.compareAndSet(writerLocation, null )
89
+ if (readers.value != 0 ) reader.value?. let { throw concurrentRW(it) }
87
90
}
88
91
}
89
92
}
0 commit comments