Make Codec2RecipeSerializer thread safe
This commit is contained in:
parent
933521df10
commit
182bb4c8ba
@ -18,16 +18,25 @@ import ru.dbotthepony.mc.otm.core.set
|
|||||||
import ru.dbotthepony.mc.otm.core.util.readBinaryJsonWithCodecIndirect
|
import ru.dbotthepony.mc.otm.core.util.readBinaryJsonWithCodecIndirect
|
||||||
import ru.dbotthepony.mc.otm.core.util.writeBinaryJsonWithCodec
|
import ru.dbotthepony.mc.otm.core.util.writeBinaryJsonWithCodec
|
||||||
import kotlin.collections.ArrayDeque
|
import kotlin.collections.ArrayDeque
|
||||||
|
import kotlin.concurrent.getOrSet
|
||||||
|
|
||||||
class Codec2RecipeSerializer<S : Recipe<*>> private constructor(
|
class Codec2RecipeSerializer<S : Recipe<*>> private constructor(
|
||||||
val empty: S?,
|
val empty: S?,
|
||||||
private val id: ArrayDeque<ResourceLocation>,
|
|
||||||
|
/**
|
||||||
|
* [ThreadLocal] because optimization mods can (and probably should) parallelize recipe deserialization,
|
||||||
|
* since RecipeSerializers are expected to be stateless. [Codec2RecipeSerializer], however, is stateful (threading PoV).
|
||||||
|
* To make it stateless, [ThreadLocal] is used.
|
||||||
|
*/
|
||||||
|
private val idStack: ThreadLocal<ArrayDeque<ResourceLocation>>,
|
||||||
codec: (Codec2RecipeSerializer<S>.Context) -> Codec<S>,
|
codec: (Codec2RecipeSerializer<S>.Context) -> Codec<S>,
|
||||||
) : Codec<S>, RecipeSerializer<S> {
|
) : Codec<S>, RecipeSerializer<S> {
|
||||||
constructor(empty: S?, codec: (Codec2RecipeSerializer<S>.Context) -> Codec<S>) : this(empty, ArrayDeque(), codec)
|
constructor(empty: S?, codec: (Codec2RecipeSerializer<S>.Context) -> Codec<S>) : this(empty, ThreadLocal(), codec)
|
||||||
constructor(supplier: (Codec2RecipeSerializer<S>.Context) -> Codec<S>) : this(null, supplier)
|
constructor(supplier: (Codec2RecipeSerializer<S>.Context) -> Codec<S>) : this(null, supplier)
|
||||||
|
|
||||||
private val codec = codec.invoke(Context())
|
private val codec = codec.invoke(Context())
|
||||||
|
private val id: ArrayDeque<ResourceLocation>
|
||||||
|
get() = idStack.getOrSet { ArrayDeque() }
|
||||||
|
|
||||||
inner class Context() {
|
inner class Context() {
|
||||||
val id: ResourceLocation
|
val id: ResourceLocation
|
||||||
@ -65,7 +74,7 @@ class Codec2RecipeSerializer<S : Recipe<*>> private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun <O : Recipe<*>> xmap(to: (S) -> O, from: (O) -> S): Codec2RecipeSerializer<O> {
|
fun <O : Recipe<*>> xmap(to: (S) -> O, from: (O) -> S): Codec2RecipeSerializer<O> {
|
||||||
return Codec2RecipeSerializer(empty?.let(to), id) { _ ->
|
return Codec2RecipeSerializer(empty?.let(to), idStack) { _ ->
|
||||||
codec.xmap(to, from)
|
codec.xmap(to, from)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user