-
Notifications
You must be signed in to change notification settings - Fork 58
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #326 from arkivanov/optimize-SharedList-for-native
Optimized SharedList for Native
- Loading branch information
Showing
5 changed files
with
194 additions
and
128 deletions.
There are no files selected for viewing
164 changes: 164 additions & 0 deletions
164
reaktive/src/nativeCommonMain/kotlin/com/badoo/reaktive/utils/CopyOnWriteList.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
package com.badoo.reaktive.utils | ||
|
||
import com.badoo.reaktive.utils.atomic.AtomicList | ||
import com.badoo.reaktive.utils.atomic.add | ||
import com.badoo.reaktive.utils.atomic.clear | ||
import com.badoo.reaktive.utils.atomic.get | ||
import com.badoo.reaktive.utils.atomic.isEmpty | ||
import com.badoo.reaktive.utils.atomic.plusAssign | ||
import com.badoo.reaktive.utils.atomic.remove | ||
import com.badoo.reaktive.utils.atomic.removeAt | ||
import com.badoo.reaktive.utils.atomic.set | ||
import com.badoo.reaktive.utils.atomic.size | ||
|
||
internal class CopyOnWriteList<T>(initalList: List<T> = emptyList()) : MutableList<T> { | ||
|
||
private val delegate = AtomicList(initalList) | ||
|
||
override val size: Int get() = delegate.size | ||
|
||
override fun contains(element: T): Boolean = delegate.value.contains(element) | ||
|
||
override fun containsAll(elements: Collection<T>): Boolean = delegate.value.containsAll(elements) | ||
|
||
override fun get(index: Int): T = delegate[index] | ||
|
||
override fun indexOf(element: T): Int = delegate.value.indexOf(element) | ||
|
||
override fun isEmpty(): Boolean = delegate.isEmpty | ||
|
||
override fun iterator(): MutableIterator<T> = MutableListIteratorImpl(this, 0) | ||
|
||
override fun lastIndexOf(element: T): Int = delegate.value.lastIndexOf(element) | ||
|
||
override fun add(element: T): Boolean { | ||
delegate += element | ||
|
||
return true | ||
} | ||
|
||
override fun add(index: Int, element: T) { | ||
delegate.add(index, element) | ||
} | ||
|
||
override fun addAll(index: Int, elements: Collection<T>): Boolean { | ||
if (elements.isEmpty()) { | ||
return false | ||
} | ||
|
||
val oldList = delegate.value | ||
val newList = ArrayList<T>(oldList.size + elements.size) | ||
|
||
for (i in 0 until index) { | ||
newList.add(oldList[i]) | ||
} | ||
|
||
newList.addAll(elements) | ||
|
||
for (i in index until oldList.size) { | ||
newList.add(oldList[i]) | ||
} | ||
|
||
delegate.value = newList | ||
|
||
return true | ||
} | ||
|
||
override fun addAll(elements: Collection<T>): Boolean { | ||
if (elements.isEmpty()) { | ||
return false | ||
} | ||
|
||
delegate.value = delegate.value + elements | ||
|
||
return true | ||
} | ||
|
||
override fun clear() { | ||
delegate.clear() | ||
} | ||
|
||
override fun listIterator(): MutableListIterator<T> = MutableListIteratorImpl(this, 0) | ||
|
||
override fun listIterator(index: Int): MutableListIterator<T> = MutableListIteratorImpl(this, index) | ||
|
||
override fun remove(element: T): Boolean = delegate.remove(element) | ||
|
||
override fun removeAll(elements: Collection<T>): Boolean { | ||
val oldList = delegate.value | ||
val newList = oldList - elements | ||
delegate.value = newList | ||
|
||
return newList.size < oldList.size | ||
} | ||
|
||
override fun removeAt(index: Int): T = delegate.removeAt(index) | ||
|
||
override fun retainAll(elements: Collection<T>): Boolean { | ||
val oldList = delegate.value | ||
val newList = oldList.filter(elements::contains) | ||
delegate.value = newList | ||
|
||
return newList.size < oldList.size | ||
} | ||
|
||
override fun set(index: Int, element: T): T = delegate.set(index, element) | ||
|
||
override fun subList(fromIndex: Int, toIndex: Int): MutableList<T> { | ||
throw NotImplementedError() // It's tricky and we don't need it at the moment | ||
} | ||
|
||
override fun equals(other: Any?): Boolean = delegate.value == other | ||
|
||
override fun hashCode(): Int = delegate.value.hashCode() | ||
|
||
private inner class MutableListIteratorImpl<T>( | ||
private val list: MutableList<T>, | ||
private var index: Int | ||
) : MutableListIterator<T> { | ||
private var lastIndex = -1 | ||
|
||
override fun hasPrevious(): Boolean = index > 0 | ||
override fun hasNext(): Boolean = index < list.size | ||
|
||
override fun previousIndex(): Int = index - 1 | ||
override fun nextIndex(): Int = index | ||
|
||
override fun previous(): T { | ||
if (index <= 0) { | ||
throw NoSuchElementException() | ||
} | ||
|
||
lastIndex = --index | ||
|
||
return list[lastIndex] | ||
} | ||
|
||
override fun next(): T { | ||
if (index >= list.size) { | ||
throw NoSuchElementException() | ||
} | ||
|
||
lastIndex = index++ | ||
|
||
return list[lastIndex] | ||
} | ||
|
||
override fun set(element: T) { | ||
list[lastIndex] = element | ||
} | ||
|
||
override fun add(element: T) { | ||
list.add(index++, element) | ||
lastIndex = -1 | ||
} | ||
|
||
override fun remove() { | ||
check(lastIndex != -1) { "Call next() or previous() before removing element from the iterator." } | ||
|
||
list.removeAt(lastIndex) | ||
index = lastIndex | ||
lastIndex = -1 | ||
} | ||
} | ||
} |
146 changes: 23 additions & 123 deletions
146
reaktive/src/nativeCommonMain/kotlin/com/badoo/reaktive/utils/SharedList.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,164 +1,64 @@ | ||
package com.badoo.reaktive.utils | ||
|
||
import com.badoo.reaktive.utils.atomic.AtomicList | ||
import com.badoo.reaktive.utils.atomic.add | ||
import com.badoo.reaktive.utils.atomic.clear | ||
import com.badoo.reaktive.utils.atomic.get | ||
import com.badoo.reaktive.utils.atomic.isEmpty | ||
import com.badoo.reaktive.utils.atomic.plusAssign | ||
import com.badoo.reaktive.utils.atomic.remove | ||
import com.badoo.reaktive.utils.atomic.removeAt | ||
import com.badoo.reaktive.utils.atomic.set | ||
import com.badoo.reaktive.utils.atomic.size | ||
|
||
internal actual class SharedList<T> actual constructor(initialCapacity: Int) : MutableList<T> { | ||
|
||
private val delegate = AtomicList<T>(emptyList()) | ||
private val helper = | ||
MutableFreezableHelper<MutableList<T>, ArrayList<T>, CopyOnWriteList<T>>( | ||
mutableFactory = { ArrayList(initialCapacity) }, | ||
freezableFactory = { CopyOnWriteList(it ?: emptyList()) } | ||
) | ||
|
||
private val delegate: MutableList<T> get() = helper.obj | ||
|
||
override val size: Int get() = delegate.size | ||
|
||
override fun contains(element: T): Boolean = delegate.value.contains(element) | ||
override fun contains(element: T): Boolean = delegate.contains(element) | ||
|
||
override fun containsAll(elements: Collection<T>): Boolean = delegate.value.containsAll(elements) | ||
override fun containsAll(elements: Collection<T>): Boolean = delegate.containsAll(elements) | ||
|
||
override fun get(index: Int): T = delegate[index] | ||
|
||
override fun indexOf(element: T): Int = delegate.value.indexOf(element) | ||
override fun indexOf(element: T): Int = delegate.indexOf(element) | ||
|
||
override fun isEmpty(): Boolean = delegate.isEmpty | ||
override fun isEmpty(): Boolean = delegate.isEmpty() | ||
|
||
override fun iterator(): MutableIterator<T> = MutableListIteratorImpl(this, 0) | ||
override fun iterator(): MutableIterator<T> = delegate.iterator() | ||
|
||
override fun lastIndexOf(element: T): Int = delegate.value.lastIndexOf(element) | ||
override fun lastIndexOf(element: T): Int = delegate.lastIndexOf(element) | ||
|
||
override fun add(element: T): Boolean { | ||
delegate += element | ||
|
||
return true | ||
} | ||
override fun add(element: T): Boolean = delegate.add(element) | ||
|
||
override fun add(index: Int, element: T) { | ||
delegate.add(index, element) | ||
} | ||
|
||
override fun addAll(index: Int, elements: Collection<T>): Boolean { | ||
if (elements.isEmpty()) { | ||
return false | ||
} | ||
|
||
val oldList = delegate.value | ||
val newList = ArrayList<T>(oldList.size + elements.size) | ||
|
||
for (i in 0 until index) { | ||
newList.add(oldList[i]) | ||
} | ||
|
||
newList.addAll(elements) | ||
|
||
for (i in index until oldList.size) { | ||
newList.add(oldList[i]) | ||
} | ||
|
||
delegate.value = newList | ||
|
||
return true | ||
} | ||
|
||
override fun addAll(elements: Collection<T>): Boolean { | ||
if (elements.isEmpty()) { | ||
return false | ||
} | ||
override fun addAll(index: Int, elements: Collection<T>): Boolean = delegate.addAll(index, elements) | ||
|
||
delegate.value = delegate.value + elements | ||
|
||
return true | ||
} | ||
override fun addAll(elements: Collection<T>): Boolean = delegate.addAll(elements) | ||
|
||
override fun clear() { | ||
delegate.clear() | ||
} | ||
|
||
override fun listIterator(): MutableListIterator<T> = MutableListIteratorImpl(this, 0) | ||
override fun listIterator(): MutableListIterator<T> = delegate.listIterator() | ||
|
||
override fun listIterator(index: Int): MutableListIterator<T> = MutableListIteratorImpl(this, index) | ||
override fun listIterator(index: Int): MutableListIterator<T> = delegate.listIterator(index) | ||
|
||
override fun remove(element: T): Boolean = delegate.remove(element) | ||
|
||
override fun removeAll(elements: Collection<T>): Boolean { | ||
val oldList = delegate.value | ||
val newList = oldList - elements | ||
delegate.value = newList | ||
|
||
return newList.size < oldList.size | ||
} | ||
override fun removeAll(elements: Collection<T>): Boolean = delegate.removeAll(elements) | ||
|
||
override fun removeAt(index: Int): T = delegate.removeAt(index) | ||
|
||
override fun retainAll(elements: Collection<T>): Boolean { | ||
val oldList = delegate.value | ||
val newList = oldList.filter(elements::contains) | ||
delegate.value = newList | ||
|
||
return newList.size < oldList.size | ||
} | ||
override fun retainAll(elements: Collection<T>): Boolean = delegate.retainAll(elements) | ||
|
||
override fun set(index: Int, element: T): T = delegate.set(index, element) | ||
|
||
override fun subList(fromIndex: Int, toIndex: Int): MutableList<T> { | ||
throw NotImplementedError() // It's tricky and we need it at the moment | ||
throw NotImplementedError() // It's tricky and we don't need it at the moment | ||
} | ||
|
||
override fun equals(other: Any?): Boolean = delegate.value == other | ||
|
||
override fun hashCode(): Int = delegate.value.hashCode() | ||
|
||
private inner class MutableListIteratorImpl<T>( | ||
private val list: MutableList<T>, | ||
private var index: Int | ||
) : MutableListIterator<T> { | ||
private var lastIndex = -1 | ||
|
||
override fun hasPrevious(): Boolean = index > 0 | ||
override fun hasNext(): Boolean = index < list.size | ||
|
||
override fun previousIndex(): Int = index - 1 | ||
override fun nextIndex(): Int = index | ||
|
||
override fun previous(): T { | ||
if (index <= 0) { | ||
throw NoSuchElementException() | ||
} | ||
|
||
lastIndex = --index | ||
override fun equals(other: Any?): Boolean = delegate == other | ||
|
||
return list[lastIndex] | ||
} | ||
|
||
override fun next(): T { | ||
if (index >= list.size) { | ||
throw NoSuchElementException() | ||
} | ||
|
||
lastIndex = index++ | ||
|
||
return list[lastIndex] | ||
} | ||
|
||
override fun set(element: T) { | ||
list[lastIndex] = element | ||
} | ||
|
||
override fun add(element: T) { | ||
list.add(index++, element) | ||
lastIndex = -1 | ||
} | ||
|
||
override fun remove() { | ||
check(lastIndex != -1) { "Call next() or previous() before removing element from the iterator." } | ||
|
||
list.removeAt(lastIndex) | ||
index = lastIndex | ||
lastIndex = -1 | ||
} | ||
} | ||
override fun hashCode(): Int = delegate.hashCode() | ||
} |
5 changes: 3 additions & 2 deletions
5
.../reaktive/utils/SharedListIteratorTest.kt → ...tive/utils/CopyOnWriteListIteratorTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
5 changes: 3 additions & 2 deletions
5
...om/badoo/reaktive/utils/SharedListTest.kt → ...doo/reaktive/utils/CopyOnWriteListTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
reaktive/src/nativeCommonTest/kotlin/com/badoo/reaktive/utils/queue/CopyOnWriteQueueTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
package com.badoo.reaktive.utils.queue | ||
|
||
import com.badoo.reaktive.utils.freeze | ||
import kotlin.native.concurrent.freeze | ||
|
||
class CopyOnWriteQueueTest : QueueTests by QueueTestsImpl(CopyOnWriteQueue<String?>().freeze()) |