Add an option for EventTargetGroup to be thread-safe
This commit is contained in:
parent
27cf3c5a50
commit
f958b9c364
6 changed files with 15 additions and 27 deletions
|
@ -1,9 +1,10 @@
|
|||
package space.blokk.event
|
||||
|
||||
abstract class EventTargetGroup<T : EventTarget<*>> : Iterable<T> {
|
||||
// TODO: Allow using a different collection implementation (in order to allow concurrency)
|
||||
private val targets: MutableCollection<T> = mutableSetOf()
|
||||
private val listeners = mutableSetOf<Listener>()
|
||||
import java.util.concurrent.CopyOnWriteArraySet
|
||||
|
||||
abstract class EventTargetGroup<T : EventTarget<*>>(threadSafe: Boolean = false) : Iterable<T> {
|
||||
private val targets: MutableSet<T> = if (threadSafe) CopyOnWriteArraySet() else HashSet()
|
||||
private val listeners: MutableSet<Listener> = if (threadSafe) CopyOnWriteArraySet() else HashSet()
|
||||
|
||||
/**
|
||||
* Register a listener for all elements in this group.
|
||||
|
@ -11,8 +12,8 @@ abstract class EventTargetGroup<T : EventTarget<*>> : Iterable<T> {
|
|||
* because this may lead to strange behaviour.
|
||||
*/
|
||||
fun <T : Listener> registerListener(listener: T): T {
|
||||
targets.forEach { it.eventBus.register(listener) }
|
||||
listeners.add(listener)
|
||||
targets.forEach { it.eventBus.register(listener) }
|
||||
return listener
|
||||
}
|
||||
|
||||
|
@ -28,15 +29,16 @@ abstract class EventTargetGroup<T : EventTarget<*>> : Iterable<T> {
|
|||
override fun iterator(): Iterator<T> = targets.iterator()
|
||||
|
||||
protected fun addTarget(target: T) {
|
||||
listeners.forEach { target.eventBus.register(it) }
|
||||
targets.add(target)
|
||||
listeners.forEach { target.eventBus.register(it) }
|
||||
}
|
||||
|
||||
protected fun removeTarget(target: T) {
|
||||
targets.remove(target)
|
||||
listeners.forEach { target.eventBus.unregister(it) }
|
||||
}
|
||||
|
||||
class Public<T : EventTarget<*>> : EventTargetGroup<T>() {
|
||||
class Mutable<T : EventTarget<*>>(threadSafe: Boolean = false) : EventTargetGroup<T>(threadSafe) {
|
||||
fun add(target: T) = addTarget(target)
|
||||
fun remove(target: T) = removeTarget(target)
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ abstract class World(val uuid: UUID) {
|
|||
/**
|
||||
* All entities in this world. Use [spawnEntity] for spawning new ones.
|
||||
*/
|
||||
abstract val entities: EventTargetGroup.Public<Entity>
|
||||
abstract val entities: EventTargetGroup.Mutable<Entity>
|
||||
|
||||
/**
|
||||
* All currently loaded chunks of this world.
|
||||
|
|
|
@ -5,10 +5,11 @@ import com.sksamuel.hoplite.ConfigLoader
|
|||
import com.sksamuel.hoplite.ConfigSource
|
||||
import space.blokk.config.BlokkConfig
|
||||
import space.blokk.event.EventBus
|
||||
import space.blokk.event.EventTargetGroup
|
||||
import space.blokk.logging.BlokkLoggingOutputProvider
|
||||
import space.blokk.logging.Logger
|
||||
import space.blokk.net.BlokkSocketServer
|
||||
import space.blokk.player.PlayerGroup
|
||||
import space.blokk.player.Player
|
||||
import space.blokk.plugin.BlokkPluginManager
|
||||
import space.blokk.server.Server
|
||||
import space.blokk.server.event.ServerEvent
|
||||
|
@ -27,7 +28,7 @@ class BlokkServer internal constructor() : Server {
|
|||
override val eventBus = EventBus(ServerEvent::class, scope, logger)
|
||||
|
||||
override val sessions by socketServer::sessions
|
||||
override val players = PlayerGroup()
|
||||
override val players = EventTargetGroup.Mutable<Player>(true)
|
||||
override val pluginManager = BlokkPluginManager(this)
|
||||
|
||||
val keyPair: KeyPair
|
||||
|
|
|
@ -11,6 +11,7 @@ import io.netty.channel.kqueue.KQueueServerSocketChannel
|
|||
import io.netty.channel.nio.NioEventLoopGroup
|
||||
import io.netty.channel.socket.nio.NioServerSocketChannel
|
||||
import space.blokk.BlokkServer
|
||||
import space.blokk.event.EventTargetGroup
|
||||
import space.blokk.logging.Logger
|
||||
|
||||
class BlokkSocketServer(val server: BlokkServer) {
|
||||
|
@ -31,7 +32,7 @@ class BlokkSocketServer(val server: BlokkServer) {
|
|||
.childOption(ChannelOption.TCP_NODELAY, true)
|
||||
.childHandler(BlokkChannelInitializer(this))
|
||||
|
||||
internal val sessions = SessionGroup()
|
||||
internal val sessions = EventTargetGroup.Mutable<Session>(true)
|
||||
|
||||
fun bind() {
|
||||
bootstrap.bind(server.config.host, server.config.port)
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
package space.blokk.net
|
||||
|
||||
import space.blokk.event.EventTargetGroup
|
||||
|
||||
class SessionGroup : EventTargetGroup<Session>() {
|
||||
fun add(target: Session) = addTarget(target)
|
||||
fun remove(target: Session) = removeTarget(target)
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
package space.blokk.player
|
||||
|
||||
import space.blokk.event.EventTargetGroup
|
||||
|
||||
class PlayerGroup : EventTargetGroup<Player>() {
|
||||
fun add(target: Player) = addTarget(target)
|
||||
fun remove(target: Player) = removeTarget(target)
|
||||
}
|
Reference in a new issue