Skip to content

Delegate properties to atomics #3265

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
# Kotlin
version=1.6.4-SNAPSHOT
group=org.jetbrains.kotlinx
kotlin_version=1.7.20
kotlin_version=1.7.21

# Dependencies
junit_version=4.12
junit5_version=5.7.0
atomicfu_version=0.18.4
atomicfu_version=0.18.5
knit_version=0.4.0
html_version=0.7.2
lincheck_version=2.14.1
Expand Down Expand Up @@ -58,4 +58,5 @@ org.gradle.jvmargs=-Xmx3g

kotlin.mpp.enableCompatibilityMetadataVariant=true
kotlin.mpp.stability.nowarn=true
kotlinx.atomicfu.enableIrTransformation=true
kotlinx.atomicfu.enableJvmIrTransformation=true
kotlinx.atomicfu.enableJsIrTransformation=true
7 changes: 3 additions & 4 deletions kotlinx-coroutines-core/common/src/Await.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package kotlinx.coroutines

import kotlinx.atomicfu.*
import kotlin.coroutines.*
import kotlin.jvm.*

/**
* Awaits for completion of given deferred values without blocking a thread and resumes normally with the list of values
Expand Down Expand Up @@ -103,10 +104,8 @@ private class AwaitAll<T>(private val deferreds: Array<out Deferred<T>>) {
private inner class AwaitAllNode(private val continuation: CancellableContinuation<List<T>>) : JobNode() {
lateinit var handle: DisposableHandle

private val _disposer = atomic<DisposeHandlersOnCancel?>(null)
var disposer: DisposeHandlersOnCancel?
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

while we are here, it seems like it should just be

@Volatile
private var disposer: DisposeHandlersOnCancel? = null

get() = _disposer.value
set(value) { _disposer.value = value }
@Volatile
var disposer: DisposeHandlersOnCancel? = null

override fun invoke(cause: Throwable?) {
if (cause != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ internal open class CancellableContinuationImpl<in T>(
private val parentHandle: DisposableHandle?
get() = _parentHandle.value

internal val state: Any? get() = _state.value
internal val state: Any? by _state

public override val isActive: Boolean get() = state is NotCompleted

Expand Down
2 changes: 1 addition & 1 deletion kotlinx-coroutines-core/common/src/CompletionState.kt
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ internal open class CompletedExceptionally(
handled: Boolean = false
) {
private val _handled = atomic(handled)
val handled: Boolean get() = _handled.value
val handled: Boolean by _handled
fun makeHandled(): Boolean = _handled.compareAndSet(false, true)
override fun toString(): String = "$classSimpleName[$cause]"
}
Expand Down
4 changes: 1 addition & 3 deletions kotlinx-coroutines-core/common/src/EventLoop.common.kt
Original file line number Diff line number Diff line change
Expand Up @@ -185,9 +185,7 @@ internal abstract class EventLoopImplBase: EventLoopImplPlatform(), Delay {
private val _delayed = atomic<DelayedTaskQueue?>(null)

private val _isCompleted = atomic(false)
private var isCompleted
get() = _isCompleted.value
set(value) { _isCompleted.value = value }
private var isCompleted: Boolean by _isCompleted

override val isEmpty: Boolean get() {
if (!isUnconfinedQueueEmpty) return false
Expand Down
16 changes: 4 additions & 12 deletions kotlinx-coroutines-core/common/src/JobSupport.kt
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,7 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren
private val _state = atomic<Any?>(if (active) EMPTY_ACTIVE else EMPTY_NEW)

private val _parentHandle = atomic<ChildHandle?>(null)
internal var parentHandle: ChildHandle?
get() = _parentHandle.value
set(value) { _parentHandle.value = value }
internal var parentHandle: ChildHandle? by _parentHandle

override val parent: Job?
get() = parentHandle?.parent
Expand Down Expand Up @@ -1080,19 +1078,13 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren
rootCause: Throwable?
) : SynchronizedObject(), Incomplete {
private val _isCompleting = atomic(isCompleting)
var isCompleting: Boolean
get() = _isCompleting.value
set(value) { _isCompleting.value = value }
var isCompleting: Boolean by _isCompleting

private val _rootCause = atomic(rootCause)
var rootCause: Throwable? // NOTE: rootCause is kept even when SEALED
get() = _rootCause.value
set(value) { _rootCause.value = value }
var rootCause: Throwable? by _rootCause // NOTE: rootCause is kept even when SEALED

private val _exceptionsHolder = atomic<Any?>(null)
private var exceptionsHolder: Any? // Contains null | Throwable | ArrayList | SEALED
get() = _exceptionsHolder.value
set(value) { _exceptionsHolder.value = value }
private var exceptionsHolder: Any? by _exceptionsHolder // Contains null | Throwable | ArrayList | SEALED

// Note: cannot be modified when sealed
val isSealed: Boolean get() = exceptionsHolder === SEALED
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,19 +51,13 @@ internal class ArrayBroadcastChannel<E>(
// head, tail, and size are guarded by bufferLock

private val _head = atomic(0L)
private var head: Long // do modulo on use of head
get() = _head.value
set(value) { _head.value = value }
private var head: Long by _head // do modulo on use of head

private val _tail = atomic(0L)
private var tail: Long // do modulo on use of tail
get() = _tail.value
set(value) { _tail.value = value }
private var tail: Long by _tail // do modulo on use of tail

private val _size = atomic(0)
private var size: Int
get() = _size.value
set(value) { _size.value = value }
private var size: Int by _size

@Suppress("DEPRECATION")
private val subscribers = subscriberList<Subscriber<E>>()
Expand Down Expand Up @@ -196,9 +190,7 @@ internal class ArrayBroadcastChannel<E>(
private val subLock = ReentrantLock()

private val _subHead = atomic(0L)
var subHead: Long // guarded by subLock
get() = _subHead.value
set(value) { _subHead.value = value }
var subHead: Long by _subHead // guarded by subLock

override val isBufferAlwaysEmpty: Boolean get() = false
override val isBufferEmpty: Boolean get() = subHead >= broadcastChannel.tail
Expand Down
2 changes: 1 addition & 1 deletion kotlinx-coroutines-core/common/src/internal/Atomic.kt
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public abstract class AtomicOp<in T> : OpDescriptor() {
private val _consensus = atomic<Any?>(NO_DECISION)

// Returns NO_DECISION when there is not decision yet
val consensus: Any? get() = _consensus.value
val consensus: Any? by _consensus

val isDecided: Boolean get() = _consensus.value !== NO_DECISION

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ internal abstract class ConcurrentLinkedListNode<N : ConcurrentLinkedListNode<N>
// Pointer to the previous node, updates in [remove] function.
private val _prev = atomic(prev)

private val nextOrClosed get() = _next.value
private val nextOrClosed: Any? by _next

/**
* Returns the next segment or `null` of the one does not exist,
Expand All @@ -122,7 +122,7 @@ internal abstract class ConcurrentLinkedListNode<N : ConcurrentLinkedListNode<N>
*/
val isTail: Boolean get() = next == null

val prev: N? get() = _prev.value
val prev: N? by _prev

/**
* Cleans the pointer to the previous node.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,7 @@ class ChannelUndeliveredElementTest : TestBase() {
private class Resource(val value: String) {
private val _cancelled = atomic(false)

val isCancelled: Boolean
get() = _cancelled.value
val isCancelled: Boolean by _cancelled

fun cancel() {
check(!_cancelled.getAndSet(true)) { "Already cancelled" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ public actual open class LockFreeLinkedListNode {
queue.correctPrev(op) // queue head is never removed, so null result can only mean RETRY_ATOMIC

private val _affectedNode = atomic<Node?>(null)
final override val affectedNode: Node? get() = _affectedNode.value
final override val affectedNode: Node? by _affectedNode
final override val originalNext: Node get() = queue

override fun retry(affected: Node, next: Any): Boolean = next !== queue
Expand Down Expand Up @@ -368,8 +368,8 @@ public actual open class LockFreeLinkedListNode {
}
}

final override val affectedNode: Node? get() = _affectedNode.value
final override val originalNext: Node? get() = _originalNext.value
final override val affectedNode: Node? by _affectedNode
final override val originalNext: Node? by _originalNext

// check node predicates here, must signal failure if affect is not of type T
protected override fun failure(affected: Node): Any? =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ internal class ConcurrentWeakMap<K : Any, V: Any>(
private val core = atomic(Core(MIN_CAPACITY))
private val weakRefQueue: ReferenceQueue<K>? = if (weakRefQueue) ReferenceQueue() else null

override val size: Int
get() = _size.value
override val size: Int by _size

private fun decrementSize() { _size.decrementAndGet() }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ internal class CoroutineScheduler(

// This is used a "stop signal" for close and shutdown functions
private val _isTerminated = atomic(false)
val isTerminated: Boolean get() = _isTerminated.value
val isTerminated: Boolean by _isTerminated

companion object {
// A symbol to mark workers that are not in parkedWorkersStack
Expand Down