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.writeBinaryJsonWithCodec
|
||||
import kotlin.collections.ArrayDeque
|
||||
import kotlin.concurrent.getOrSet
|
||||
|
||||
class Codec2RecipeSerializer<S : Recipe<*>> private constructor(
|
||||
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<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)
|
||||
|
||||
private val codec = codec.invoke(Context())
|
||||
private val id: ArrayDeque<ResourceLocation>
|
||||
get() = idStack.getOrSet { ArrayDeque() }
|
||||
|
||||
inner class Context() {
|
||||
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> {
|
||||
return Codec2RecipeSerializer(empty?.let(to), id) { _ ->
|
||||
return Codec2RecipeSerializer(empty?.let(to), idStack) { _ ->
|
||||
codec.xmap(to, from)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user