```class ExternalObject(val id: Int) { fun add...
# kotlin-native
o
Copy code
class ExternalObject(val id: Int) {
    fun addRef() = println("addref on $id")
    fun release() = println("release on $id")
}

interface ObjectOwner {
    fun addObject(obj: ExternalObject)
    fun addOwner(owner: ObjectOwner)
    fun clear()
}

fun ObjectOwner.makeObject(id: Int): ExternalObject {
    val result = ExternalObject(id)
    this.addObject(result)
    return result
}

open class Holder : ObjectOwner {
    val objects = mutableListOf<ExternalObject>()
    val owners = mutableListOf<ObjectOwner>()

    constructor(parent: ObjectOwner? = null) {
        if (parent != null) parent.addOwner(this)
    }

    override fun addObject(obj: ExternalObject): Unit {
        // If we want more aggressive release strategy, we can use MutableSet for `objects`
        // and release ASAP.
        objects.add(obj)
        obj.addRef()
    }

    override fun addOwner(owner: ObjectOwner): Unit {
        owners.add(owner)
    }

    override fun clear() {
        for (obj in objects) obj.release()
        for (owner in owners) owner.clear()
    }
}

class FieldOwner(parent: ObjectOwner) : Holder(parent) {

    var objectField: ExternalObject? = null
        set(value: ExternalObject?) {
            field = value
            if (value != null) addObject(value)
        }

        get() = field
}


inline fun <T> scoped(block: ObjectOwner.() -> T): T {
    val scope = Holder()
    try {
        return scope.block()
    } finally {
        scope.clear()
    }
}

fun main(args: Array<String>) {
    scoped {
        val owner = FieldOwner(this)
        owner.objectField = makeObject(1)
        scoped {
            owner.objectField = makeObject(3)

        }
        owner.objectField = makeObject(2)
    }
}
shows how one could think of such a cases