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

nativeCommonMain.co.touchlab.stately.collections.CopyOnWriteList.kt Maven / Gradle / Ivy

There is a newer version: 2.1.0
Show newest version
/*
 * Copyright (C) 2018 Touchlab, 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 co.touchlab.stately.collections

import co.touchlab.stately.concurrency.Lock
import kotlin.native.concurrent.AtomicInt
import kotlin.native.concurrent.AtomicReference
import kotlin.native.concurrent.freeze

class CopyOnWriteList(elements: Collection) : MutableList {

    private val listData = AtomicReference>(ArrayList(elements).freeze())
    private val instanceLock = Lock()

    init {
        freeze()
    }

    constructor() : this(ArrayList(0))
    constructor(initialCapacity: Int = 0) : this(ArrayList(initialCapacity))

    private inline fun  modifyList(proc: (MutableList) -> R): R {
        instanceLock.lock()

        try {
            val mutableList = ArrayList(listData.value)
            val result = proc(mutableList)
            listData.value = mutableList.freeze()

            return result
        } finally {
            instanceLock.unlock()
        }
    }

  /*private inline fun  modifyListLockless(proc:(MutableList)->R):R{
      var updated = false
      var result:R? = null
      while (!updated){
          val orig = listData.value
          val mutableList = ArrayList(orig)
          result = proc(mutableList)
          updated = listData.compareAndSet(orig, mutableList.freeze())
      }

      return result!!
  }*/

    override val size: Int
        get() = listData.value.size

    override fun contains(element: T): Boolean = listData.value.contains(element)

    override fun containsAll(elements: Collection): Boolean = listData.value.containsAll(elements)

    override fun get(index: Int): T = listData.value.get(index)

    override fun indexOf(element: T): Int = listData.value.indexOf(element)

    override fun isEmpty(): Boolean = listData.value.isEmpty()

    override fun iterator(): MutableIterator =
        LocalIterator(listData.value)

    override fun lastIndexOf(element: T): Int = listData.value.lastIndexOf(element)

    override fun add(element: T): Boolean = modifyList { it.add(element) }

    override fun add(index: Int, element: T) = modifyList { it.add(index, element) }

    override fun addAll(index: Int, elements: Collection): Boolean = modifyList { it.addAll(index, elements) }

    override fun addAll(elements: Collection): Boolean = modifyList { it.addAll(elements) }

    override fun clear() = modifyList { it.clear() }

    override fun listIterator(): MutableListIterator =
        LocalListIterator(listData.value)

    override fun listIterator(index: Int): MutableListIterator =
        LocalListIterator(listData.value, index)

    override fun remove(element: T): Boolean = modifyList { it.remove(element) }

    override fun removeAll(elements: Collection): Boolean = modifyList { it.removeAll(elements) }

    override fun removeAt(index: Int): T = modifyList { it.removeAt(index) }

    override fun retainAll(elements: Collection): Boolean = modifyList { it.retainAll(elements) }

    override fun set(index: Int, element: T): T = modifyList { it.set(index, element) }

    override fun subList(fromIndex: Int, toIndex: Int): MutableList = modifyList { it.subList(fromIndex, toIndex) }

    private open class LocalIterator(private val list: List, startIndex: Int = 0) : MutableIterator {
        val index = AtomicInt(startIndex)
        override fun hasNext(): Boolean = list.size > index.value

        override fun next(): T = list.get(index.addAndGet(1) - 1)

        override fun remove() {
            throw UnsupportedOperationException("Can't mutate list from iterator")
        }
    }

    private class LocalListIterator(private val list: List, startIndex: Int = 0) :
        LocalIterator(list, startIndex), MutableListIterator {
        override fun hasPrevious(): Boolean = index.value > 0

        override fun nextIndex(): Int = index.value

        override fun previous(): T = list.get(index.addAndGet(-1))

        override fun previousIndex(): Int = index.value - 1

        override fun add(element: T) {
            throw UnsupportedOperationException()
        }

        override fun set(element: T) {
            throw UnsupportedOperationException()
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy