diff --git a/platform/rd-platform-community/api-dump.txt b/platform/rd-platform-community/api-dump.txt index fa52bf6d0a8b..5a2d01920d89 100644 --- a/platform/rd-platform-community/api-dump.txt +++ b/platform/rd-platform-community/api-dump.txt @@ -1,4 +1,5 @@ f:com.intellij.openapi.rd.LifetimeDisposableExKt +- sf:attachAsChildTo(com.intellij.openapi.Disposable,com.jetbrains.rd.util.lifetime.Lifetime):V - sf:createLifetime(com.intellij.openapi.Disposable):com.jetbrains.rd.util.lifetime.Lifetime - sf:createNestedDisposable(com.jetbrains.rd.util.lifetime.Lifetime,java.lang.String):com.intellij.openapi.Disposable - bs:createNestedDisposable$default(com.jetbrains.rd.util.lifetime.Lifetime,java.lang.String,I,java.lang.Object):com.intellij.openapi.Disposable diff --git a/platform/rd-platform-community/src/com/intellij/openapi/rd/LifetimeDisposableEx.kt b/platform/rd-platform-community/src/com/intellij/openapi/rd/LifetimeDisposableEx.kt index 747454410214..c0d977684d6d 100644 --- a/platform/rd-platform-community/src/com/intellij/openapi/rd/LifetimeDisposableEx.kt +++ b/platform/rd-platform-community/src/com/intellij/openapi/rd/LifetimeDisposableEx.kt @@ -3,12 +3,12 @@ package com.intellij.openapi.rd import com.intellij.openapi.Disposable import com.intellij.openapi.application.WriteIntentReadAction -import com.intellij.openapi.application.writeIntentReadAction import com.intellij.openapi.util.Disposer import com.intellij.util.ui.EDT import com.jetbrains.rd.util.lifetime.Lifetime import com.jetbrains.rd.util.lifetime.LifetimeDefinition import com.jetbrains.rd.util.lifetime.isNotAlive +import java.util.concurrent.atomic.AtomicReference /** @@ -36,6 +36,29 @@ fun Disposable.defineNestedLifetime(): LifetimeDefinition { return lifetimeDefinition } +/** + * Attaches [this] disposable as a child to [lifetime] such as the disposable will be terminated when [lifetime] terminates. + * + * When the disposable is disposed of its own, there should be no leaks because the subscription to [lifetime] is also terminated on disposal of [this]. + */ +fun Disposable.attachAsChildTo(lifetime: Lifetime) { + val disposableRef = AtomicReference(this) + val childLt = lifetime.createNested() + childLt.onTermination { + disposableRef.getAndSet(null)?.let { + Disposer.dispose(it) + } + } + + if (!Disposer.tryRegister(this) { + disposableRef.getAndSet(null)?.let { + childLt.terminate() + } + }) { + childLt.terminate() + } +} + /** * Performs an action id this disposable has not been disposed yet. * The action receives a lifetime corresponding to this disposable.