Remove structural synchronization inside SynchableGroup
Also fixed memory leak when removing remotes
This commit is contained in:
parent
05913674b1
commit
25e25b0f86
@ -180,7 +180,7 @@ class DynamicSynchableGroup<T : ISynchable>(
|
|||||||
|
|
||||||
private data class Slot<T : Any>(val synchable: T, val id: Int)
|
private data class Slot<T : Any>(val synchable: T, val id: Int)
|
||||||
|
|
||||||
private val remoteStates = CopyOnWriteArrayList<RemoteState>()
|
private val remoteStates = ArrayList<RemoteState>()
|
||||||
private val value2slot = HashMap<T, Slot<T>>()
|
private val value2slot = HashMap<T, Slot<T>>()
|
||||||
private val id2slot = Int2ObjectOpenHashMap<Slot<T>>()
|
private val id2slot = Int2ObjectOpenHashMap<Slot<T>>()
|
||||||
private val idAllocator = IDAllocator()
|
private val idAllocator = IDAllocator()
|
||||||
@ -271,7 +271,7 @@ class DynamicSynchableGroup<T : ISynchable>(
|
|||||||
value2slot.clear()
|
value2slot.clear()
|
||||||
id2slot.clear()
|
id2slot.clear()
|
||||||
|
|
||||||
remoteStates.forEach { it.clear() }
|
remoteStates.toTypedArray().forEach { it.clear() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@ import java.util.function.DoubleSupplier
|
|||||||
import java.util.function.IntSupplier
|
import java.util.function.IntSupplier
|
||||||
import java.util.function.LongSupplier
|
import java.util.function.LongSupplier
|
||||||
import java.util.function.Supplier
|
import java.util.function.Supplier
|
||||||
|
import kotlin.collections.ArrayList
|
||||||
import kotlin.concurrent.withLock
|
import kotlin.concurrent.withLock
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -56,7 +57,6 @@ import kotlin.concurrent.withLock
|
|||||||
*/
|
*/
|
||||||
@Suppress("UNUSED")
|
@Suppress("UNUSED")
|
||||||
class SynchableGroup : Observer, ISynchable, Iterable<ISynchable> {
|
class SynchableGroup : Observer, ISynchable, Iterable<ISynchable> {
|
||||||
private val lock = ReentrantLock()
|
|
||||||
private val slots = ArrayList<Slot?>()
|
private val slots = ArrayList<Slot?>()
|
||||||
private val gaps = IntAVLTreeSet()
|
private val gaps = IntAVLTreeSet()
|
||||||
private val observers = ArrayList<Slot>()
|
private val observers = ArrayList<Slot>()
|
||||||
@ -109,7 +109,7 @@ class SynchableGroup : Observer, ISynchable, Iterable<ISynchable> {
|
|||||||
val id: Int
|
val id: Int
|
||||||
|
|
||||||
private var isRemoved = false
|
private var isRemoved = false
|
||||||
val remoteSlots = CopyOnWriteArrayList<Remote.RemoteSlot>()
|
val remoteSlots = ArrayList<Remote.RemoteSlot>()
|
||||||
|
|
||||||
override fun close() {
|
override fun close() {
|
||||||
if (!isRemoved) {
|
if (!isRemoved) {
|
||||||
@ -118,7 +118,7 @@ class SynchableGroup : Observer, ISynchable, Iterable<ISynchable> {
|
|||||||
gaps.add(id)
|
gaps.add(id)
|
||||||
|
|
||||||
observers.remove(this)
|
observers.remove(this)
|
||||||
remoteSlots.forEach { it.remove() }
|
remoteSlots.toTypedArray().forEach { it.remove() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,14 +128,11 @@ class SynchableGroup : Observer, ISynchable, Iterable<ISynchable> {
|
|||||||
|
|
||||||
private fun markDirty() {
|
private fun markDirty() {
|
||||||
if (!isRemote && !isRemoved) {
|
if (!isRemote && !isRemoved) {
|
||||||
remoteSlots.forEach {
|
remoteSlots.forEach { it.markDirty() }
|
||||||
it.markDirty()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
lock.withLock {
|
|
||||||
if (synchable.shouldBeObserved) {
|
if (synchable.shouldBeObserved) {
|
||||||
observers.add(this)
|
observers.add(this)
|
||||||
}
|
}
|
||||||
@ -156,7 +153,6 @@ class SynchableGroup : Observer, ISynchable, Iterable<ISynchable> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fun add0(synchable: ISynchable): Closeable {
|
fun add0(synchable: ISynchable): Closeable {
|
||||||
return Slot(synchable)
|
return Slot(synchable)
|
||||||
@ -301,12 +297,11 @@ class SynchableGroup : Observer, ISynchable, Iterable<ISynchable> {
|
|||||||
* To get changes to be networked to remote client, [write] should be called.
|
* To get changes to be networked to remote client, [write] should be called.
|
||||||
*/
|
*/
|
||||||
inner class Remote(private val listener: Runnable) : Closeable, IRemoteState {
|
inner class Remote(private val listener: Runnable) : Closeable, IRemoteState {
|
||||||
constructor() : this(Runnable { })
|
constructor() : this(Runnable {})
|
||||||
|
|
||||||
@Volatile
|
|
||||||
private var isRemoved = false
|
private var isRemoved = false
|
||||||
internal val dirty = ConcurrentLinkedQueue<RemoteSlot>()
|
internal val dirty = ConcurrentLinkedQueue<RemoteSlot>()
|
||||||
private val remoteSlots = CopyOnWriteArrayList<RemoteSlot>()
|
private val remoteSlots = ArrayList<RemoteSlot>()
|
||||||
|
|
||||||
internal inner class RemoteSlot(val slot: Slot) {
|
internal inner class RemoteSlot(val slot: Slot) {
|
||||||
private val isDirty = AtomicBoolean()
|
private val isDirty = AtomicBoolean()
|
||||||
@ -357,6 +352,7 @@ class SynchableGroup : Observer, ISynchable, Iterable<ISynchable> {
|
|||||||
remoteSlots.remove(this)
|
remoteSlots.remove(this)
|
||||||
dirty.remove(this)
|
dirty.remove(this)
|
||||||
cleanable.clean()
|
cleanable.clean()
|
||||||
|
slot.remoteSlots.remove(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
override fun hashCode(): Int {
|
||||||
@ -369,7 +365,6 @@ class SynchableGroup : Observer, ISynchable, Iterable<ISynchable> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
lock.withLock {
|
|
||||||
slots.forEach {
|
slots.forEach {
|
||||||
if (it != null) {
|
if (it != null) {
|
||||||
addSlot(it)
|
addSlot(it)
|
||||||
@ -378,7 +373,6 @@ class SynchableGroup : Observer, ISynchable, Iterable<ISynchable> {
|
|||||||
|
|
||||||
remotes.add(this)
|
remotes.add(this)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
internal fun addSlot(slot: Slot) {
|
internal fun addSlot(slot: Slot) {
|
||||||
slot.remoteSlots.add(RemoteSlot(slot))
|
slot.remoteSlots.add(RemoteSlot(slot))
|
||||||
@ -435,8 +429,7 @@ class SynchableGroup : Observer, ISynchable, Iterable<ISynchable> {
|
|||||||
if (!isRemoved) {
|
if (!isRemoved) {
|
||||||
isRemoved = true
|
isRemoved = true
|
||||||
|
|
||||||
lock.withLock {
|
remoteSlots.toTypedArray().forEach {
|
||||||
remoteSlots.forEach {
|
|
||||||
it.remove()
|
it.remove()
|
||||||
it.slot.remoteSlots.remove(it)
|
it.slot.remoteSlots.remove(it)
|
||||||
}
|
}
|
||||||
@ -446,7 +439,6 @@ class SynchableGroup : Observer, ISynchable, Iterable<ISynchable> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val LOGGER = LogManager.getLogger()
|
private val LOGGER = LogManager.getLogger()
|
||||||
|
Loading…
Reference in New Issue
Block a user