All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.io.realm.kotlin.internal.VersionTracker.kt Maven / Gradle / Ivy

Go to download

Library code for Realm Kotlin. This artifact is not supposed to be consumed directly, but through 'io.realm.kotlin:gradle-plugin:1.11.1' instead.

There is a newer version: 3.0.0
Show newest version
/*
 * Copyright 2022 Realm Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.realm.kotlin.internal

import io.realm.kotlin.VersionId
import io.realm.kotlin.internal.interop.RealmInterop
import io.realm.kotlin.internal.interop.RealmPointer
import io.realm.kotlin.internal.platform.WeakReference
import kotlinx.atomicfu.AtomicRef
import kotlinx.atomicfu.atomic

internal typealias IntermediateReference = Pair>
/**
 * Bookkeeping of intermediate versions that needs to be closed when no longer referenced or when
 * explicitly closing a realm.
 *
 * NOTE: This is not thread safe, so synchronization should be enforced by the owner/caller.
 */
internal class VersionTracker(private val owner: BaseRealmImpl, private val log: ContextLogger) {
    // Set of currently open realms. Storing the native pointer explicitly to enable us to close
    // the realm when the RealmReference is no longer referenced anymore.
    private val intermediateReferences: AtomicRef> =
        atomic(mutableSetOf())

    fun trackReference(realmReference: FrozenRealmReference) {
        // We need a new object to update the atomic reference
        val references = mutableSetOf().apply {
            addAll(intermediateReferences.value)
        }

        realmReference.let {
            log.trace("$owner TRACK-VERSION ${realmReference.version()}")
            references.add(Pair(realmReference.dbPointer, WeakReference(it)))
        }

        intermediateReferences.value = references
    }
    /**
     * Closes any realm reference that has been reclaimed by the GC.
     *
     * @return false if there is no reference left to clean.
     */
    // Closing expired references might be done by the GC:
    // https://github.com/realm/realm-kotlin/issues/1527
    fun closeExpiredReferences() {
        // We need a new object to update the atomic reference
        val references = mutableSetOf()

        intermediateReferences.value.forEach { entry ->
            val (pointer, ref) = entry
            if (ref.get() == null) {
                log.trace("$owner CLOSE-FREED ${RealmInterop.realm_get_version_id(pointer)}")
                RealmInterop.realm_close(pointer)
            } else {
                references.add(entry)
            }
        }

        intermediateReferences.value = references
    }

    fun versions(): Set =
        // We could actually also report freed versions here!?
        intermediateReferences.value.mapNotNull { it.second.get()?.version() }.toSet()

    fun close() {
        intermediateReferences.value.forEach { (pointer, _) ->
            log.trace("$owner CLOSE-ACTIVE ${VersionId(RealmInterop.realm_get_version_id(pointer))}")
            RealmInterop.realm_close(pointer)
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy