From 77443ee801c104a7fc7dada97685fe5f055bf85e Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Thu, 10 Apr 2025 22:29:52 +0700 Subject: [PATCH] To avoid name conflicts, move dynamic synchable group map implementation to asMap property --- .../network/syncher/DynamicSynchableGroup.kt | 586 +++++++++--------- 1 file changed, 306 insertions(+), 280 deletions(-) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/network/syncher/DynamicSynchableGroup.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/network/syncher/DynamicSynchableGroup.kt index cfa06cc6e..f7664893a 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/network/syncher/DynamicSynchableGroup.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/network/syncher/DynamicSynchableGroup.kt @@ -50,7 +50,7 @@ class DynamicSynchableGroup( * first-time networking of [T] to remote */ private val writer: T.(RegistryFriendlyByteBuf) -> Unit = {}, -) : ISynchable, ReferenceSet, Int2ReferenceMap { +) : ISynchable, ReferenceSet { private inner class RemoteState(val listener: Runnable) : IRemoteState { private inner class RemoteSlot(val slot: Slot, fromConstructor: Boolean) : Runnable, Closeable { val remoteState = synchable(slot.value).createRemoteState(this) @@ -367,315 +367,341 @@ class DynamicSynchableGroup( return any } - override fun put(key: Int, value: T): T? { - val slot = Slot(value, key) - val oldSlot = id2slot.put(key, slot) + /** + * Representation of this synchable group as an [Int2ReferenceMap]. Changes made to [DynamicSynchableGroup] are reflected in this map + * and vice versa. Entries can be put at arbitrary keys, but negative keys should be avoided, since they are not efficiently + * networked, and hence will create a lot of network traffic if synchables with negative keys get frequently updated. + */ + val asMap: Int2ReferenceMap by lazy { + object : Int2ReferenceMap { + override fun isEmpty(): Boolean { + return this@DynamicSynchableGroup.isEmpty() + } - if (oldSlot?.value === value) - return value + override fun remove(key: Int): T? { + val slot = id2slot.remove(key) ?: return null + removeBySlot(slot) + return slot.value + } - if (oldSlot != null) { - remoteStates.forEach { it.remove(oldSlot) } - value2slot.remove(oldSlot.value) - } else { - idAllocator.allocate(key) - } - - value2slot[value] = slot - remoteStates.forEach { it.add(slot) } - - return oldSlot?.value - } - - override fun get(key: Int): T? { - return id2slot.get(key)?.value ?: defaultReturnValue - } - - override fun containsKey(key: Int): Boolean { - return id2slot.containsKey(key) - } - - override fun defaultReturnValue(rv: T?) { - defaultReturnValue = rv - } - - override fun defaultReturnValue(): T? { - return defaultReturnValue - } - - override fun putAll(from: Map) { - from.forEach { (k, v) -> - put(k, v) - } - } - - override fun containsValue(value: T): Boolean { - return value2slot.containsKey(value) - } - - private val entrySet: ObjectSet> by lazy(LazyThreadSafetyMode.PUBLICATION) { - object : ObjectSet> { - inner class Entry(private val ikey: Int) : Int2ReferenceMap.Entry { - override val value: T - get() = id2slot[ikey]?.value ?: throw NoSuchElementException() - - override fun setValue(newValue: T): T? { - return put(ikey, newValue) - } - - override fun getIntKey(): Int { - return ikey - } - - override fun equals(other: Any?): Boolean { - return this === other || other is Int2ReferenceMap.Entry<*> && other.intKey == ikey && other.value === id2slot[ikey]?.value - } - - override fun hashCode(): Int { - return ikey * 31 + (id2slot[ikey] as Slot?).hashCode() - } - - override fun toString(): String { - return "Map.Entry[$ikey, ${id2slot[ikey]?.value}]" - } + override fun getOrDefault(key: Int, defaultValue: T): T { + return super.getOrDefault(key, defaultValue) } override val size: Int - get() = id2slot.size + get() = this@DynamicSynchableGroup.size - override fun add(element: Int2ReferenceMap.Entry): Boolean { - return put(element.intKey, element.value) != null - } + override fun put(key: Int, value: T): T? { + val slot = Slot(value, key) + val oldSlot = id2slot.put(key, slot) - override fun addAll(elements: Collection>): Boolean { - var any = false - elements.forEach { any = add(it) || any } - return any - } + if (oldSlot?.value === value) + return value - override fun clear() { - this@DynamicSynchableGroup.clear() - } - - override fun iterator(): ObjectIterator> { - return object : ObjectIterator> { - private val parent = id2slot.int2ReferenceEntrySet().iterator() - private var last: Slot? = null - - override fun hasNext(): Boolean { - return parent.hasNext() - } - - override fun remove() { - if (last == null) - throw NoSuchElementException() - - parent.remove() - removeBySlot(last!!) - last = null - } - - override fun next(): Int2ReferenceMap.Entry { - val value = parent.next() - last = value.value - return Entry(value.intKey) - } - } - } - - override fun remove(element: Int2ReferenceMap.Entry): Boolean { - val slot = id2slot.get(element.intKey) - - if (slot?.value === element.value) { - this@DynamicSynchableGroup.removeBySlot(slot) - return true + if (oldSlot != null) { + remoteStates.forEach { it.remove(oldSlot) } + value2slot.remove(oldSlot.value) + } else { + idAllocator.allocate(key) } - return false + value2slot[value] = slot + remoteStates.forEach { it.add(slot) } + + return oldSlot?.value } - override fun removeAll(elements: Collection>): Boolean { - var any = false - elements.forEach { any = remove(it) || any } - return any + override fun get(key: Int): T? { + return id2slot.get(key)?.value ?: defaultReturnValue } - override fun retainAll(elements: Collection>): Boolean { - if (elements.isEmpty()) { - val isNotEmpty = id2slot.isNotEmpty() - this@DynamicSynchableGroup.clear() - return isNotEmpty - } - - var any = false - val itr = id2slot.int2ReferenceEntrySet().iterator() - - for (entry in itr) { - if (elements.none { it.intKey == entry.intKey && it.value === entry.value.value }) { - any = true - itr.remove() - removeBySlot(entry.value) - } - } - - return any - } - - override fun contains(element: Int2ReferenceMap.Entry): Boolean { - return id2slot.get(element.intKey)?.value === element.value - } - - override fun containsAll(elements: Collection>): Boolean { - return elements.all { contains(it) } - } - - override fun isEmpty(): Boolean { - return id2slot.isEmpty() - } - } - } - - override fun int2ReferenceEntrySet(): ObjectSet> { - return entrySet - } - - override val keys: IntSet by lazy(LazyThreadSafetyMode.PUBLICATION) { - object : IntSet { - override fun add(key: Int): Boolean { - throw UnsupportedOperationException() - } - - override fun addAll(c: IntCollection): Boolean { - throw UnsupportedOperationException() - } - - override fun addAll(elements: Collection): Boolean { - throw UnsupportedOperationException() - } - - override fun clear() { - this@DynamicSynchableGroup.clear() - } - - override fun iterator(): IntIterator { - return object : IntIterator { - private val parent = id2slot.keys.iterator() - private var last = -1 - private var hasLast = false - - override fun hasNext(): Boolean { - return parent.hasNext() - } - - override fun remove() { - if (!hasLast) - throw NoSuchElementException() - - hasLast = false - val slot = id2slot.get(last) - parent.remove() - removeBySlot(slot) - } - - override fun nextInt(): Int { - last = parent.nextInt() - hasLast = true - return last - } - } - } - - override fun remove(k: Int): Boolean { - removeBySlot(id2slot.get(k) ?: return false) - return true - } - - override fun removeAll(c: IntCollection): Boolean { - val itr = c.iterator() - var any = false - - while (itr.hasNext()) { - any = remove(itr.nextInt()) || any - } - - return any - } - - override fun removeAll(elements: Collection): Boolean { - val itr = elements.iterator() - var any = false - - while (itr.hasNext()) { - any = remove(itr.next()) || any - } - - return any - } - - override fun retainAll(c: IntCollection): Boolean { - val itr = id2slot.values.iterator() - var any = false - - for (slot in itr) { - if (!c.contains(slot.id)) { - itr.remove() - check(value2slot.remove(slot.value) == slot) - remoteStates.forEach { it.remove(slot) } - any = true - } - } - - return any - } - - override fun retainAll(elements: Collection): Boolean { - val itr = id2slot.values.iterator() - var any = false - - for (slot in itr) { - if (!elements.contains(slot.id)) { - itr.remove() - check(value2slot.remove(slot.value) == slot) - remoteStates.forEach { it.remove(slot) } - any = true - } - } - - return any - } - - override fun contains(key: Int): Boolean { + override fun containsKey(key: Int): Boolean { return id2slot.containsKey(key) } - override fun containsAll(c: IntCollection): Boolean { - return id2slot.keys.containsAll(c) + override fun defaultReturnValue(rv: T?) { + defaultReturnValue = rv } - override fun containsAll(elements: Collection): Boolean { - return id2slot.keys.containsAll(elements) + override fun defaultReturnValue(): T? { + return defaultReturnValue } - override fun isEmpty(): Boolean { - return id2slot.isEmpty() + override fun putAll(from: Map) { + from.forEach { (k, v) -> + put(k, v) + } } - override fun toArray(a: IntArray?): IntArray { - return id2slot.keys.toArray(a) + override fun containsValue(value: T): Boolean { + return value2slot.containsKey(value) } - override fun toIntArray(): IntArray { - return id2slot.keys.toIntArray() + private val entrySet: ObjectSet> by lazy(LazyThreadSafetyMode.PUBLICATION) { + object : ObjectSet> { + inner class Entry(private val ikey: Int) : Int2ReferenceMap.Entry { + override val value: T + get() = id2slot[ikey]?.value ?: throw NoSuchElementException() + + override fun setValue(newValue: T): T? { + return put(ikey, newValue) + } + + override fun getIntKey(): Int { + return ikey + } + + override fun equals(other: Any?): Boolean { + return this === other || other is Int2ReferenceMap.Entry<*> && other.intKey == ikey && other.value === id2slot[ikey]?.value + } + + override fun hashCode(): Int { + return ikey * 31 + (id2slot[ikey] as Slot?).hashCode() + } + + override fun toString(): String { + return "Map.Entry[$ikey, ${id2slot[ikey]?.value}]" + } + } + + override val size: Int + get() = id2slot.size + + override fun add(element: Int2ReferenceMap.Entry): Boolean { + return put(element.intKey, element.value) != null + } + + override fun addAll(elements: Collection>): Boolean { + var any = false + elements.forEach { any = add(it) || any } + return any + } + + override fun clear() { + this@DynamicSynchableGroup.clear() + } + + override fun iterator(): ObjectIterator> { + return object : ObjectIterator> { + private val parent = id2slot.int2ReferenceEntrySet().iterator() + private var last: Slot? = null + + override fun hasNext(): Boolean { + return parent.hasNext() + } + + override fun remove() { + if (last == null) + throw NoSuchElementException() + + parent.remove() + removeBySlot(last!!) + last = null + } + + override fun next(): Int2ReferenceMap.Entry { + val value = parent.next() + last = value.value + return Entry(value.intKey) + } + } + } + + override fun remove(element: Int2ReferenceMap.Entry): Boolean { + val slot = id2slot.get(element.intKey) + + if (slot?.value === element.value) { + this@DynamicSynchableGroup.removeBySlot(slot) + return true + } + + return false + } + + override fun removeAll(elements: Collection>): Boolean { + var any = false + elements.forEach { any = remove(it) || any } + return any + } + + override fun retainAll(elements: Collection>): Boolean { + if (elements.isEmpty()) { + val isNotEmpty = id2slot.isNotEmpty() + this@DynamicSynchableGroup.clear() + return isNotEmpty + } + + var any = false + val itr = id2slot.int2ReferenceEntrySet().iterator() + + for (entry in itr) { + if (elements.none { it.intKey == entry.intKey && it.value === entry.value.value }) { + any = true + itr.remove() + removeBySlot(entry.value) + } + } + + return any + } + + override fun contains(element: Int2ReferenceMap.Entry): Boolean { + return id2slot.get(element.intKey)?.value === element.value + } + + override fun containsAll(elements: Collection>): Boolean { + return elements.all { contains(it) } + } + + override fun isEmpty(): Boolean { + return id2slot.isEmpty() + } + } } - override val size: Int - get() = id2slot.size + override fun int2ReferenceEntrySet(): ObjectSet> { + return entrySet + } + + override val keys: IntSet by lazy(LazyThreadSafetyMode.PUBLICATION) { + object : IntSet { + override fun add(key: Int): Boolean { + throw UnsupportedOperationException() + } + + override fun addAll(c: IntCollection): Boolean { + throw UnsupportedOperationException() + } + + override fun addAll(elements: Collection): Boolean { + throw UnsupportedOperationException() + } + + override fun clear() { + this@DynamicSynchableGroup.clear() + } + + override fun iterator(): IntIterator { + return object : IntIterator { + private val parent = id2slot.keys.iterator() + private var last = -1 + private var hasLast = false + + override fun hasNext(): Boolean { + return parent.hasNext() + } + + override fun remove() { + if (!hasLast) + throw NoSuchElementException() + + hasLast = false + val slot = id2slot.get(last) + parent.remove() + removeBySlot(slot) + } + + override fun nextInt(): Int { + last = parent.nextInt() + hasLast = true + return last + } + } + } + + override fun remove(k: Int): Boolean { + removeBySlot(id2slot.get(k) ?: return false) + return true + } + + override fun removeAll(c: IntCollection): Boolean { + val itr = c.iterator() + var any = false + + while (itr.hasNext()) { + any = remove(itr.nextInt()) || any + } + + return any + } + + override fun removeAll(elements: Collection): Boolean { + val itr = elements.iterator() + var any = false + + while (itr.hasNext()) { + any = remove(itr.next()) || any + } + + return any + } + + override fun retainAll(c: IntCollection): Boolean { + val itr = id2slot.values.iterator() + var any = false + + for (slot in itr) { + if (!c.contains(slot.id)) { + itr.remove() + check(value2slot.remove(slot.value) == slot) + remoteStates.forEach { it.remove(slot) } + any = true + } + } + + return any + } + + override fun retainAll(elements: Collection): Boolean { + val itr = id2slot.values.iterator() + var any = false + + for (slot in itr) { + if (!elements.contains(slot.id)) { + itr.remove() + check(value2slot.remove(slot.value) == slot) + remoteStates.forEach { it.remove(slot) } + any = true + } + } + + return any + } + + override fun contains(key: Int): Boolean { + return id2slot.containsKey(key) + } + + override fun containsAll(c: IntCollection): Boolean { + return id2slot.keys.containsAll(c) + } + + override fun containsAll(elements: Collection): Boolean { + return id2slot.keys.containsAll(elements) + } + + override fun isEmpty(): Boolean { + return id2slot.isEmpty() + } + + override fun toArray(a: IntArray?): IntArray { + return id2slot.keys.toArray(a) + } + + override fun toIntArray(): IntArray { + return id2slot.keys.toIntArray() + } + + override val size: Int + get() = id2slot.size + } + } + + override val values: ReferenceCollection + get() = this@DynamicSynchableGroup } } - override val values: ReferenceCollection - get() = this - companion object { private const val END = 0 private const val ADD_ENTRY = 1