Make ObjectArray interface

Signed-off-by: TheMode <themode@outlook.fr>
This commit is contained in:
TheMode 2022-05-18 08:54:55 +02:00
parent 367c389bc6
commit ace42b6f46
7 changed files with 104 additions and 35 deletions

View File

@ -21,7 +21,7 @@ import static net.minestom.server.entity.Metadata.String;
import static net.minestom.server.entity.Metadata.*;
final class MetadataImpl {
static final ObjectArray<Metadata.Entry<?>> EMPTY_VALUES = new ObjectArray<>(20);
static final ObjectArray<Metadata.Entry<?>> EMPTY_VALUES = ObjectArray.singleThread(20);
static {
EMPTY_VALUES.set(TYPE_BYTE, Byte((byte) 0));

View File

@ -26,11 +26,11 @@ record BlockImpl(@NotNull Registry.BlockEntry registry,
@Nullable NBTCompound nbt,
@Nullable BlockHandler handler) implements Block {
// Block state -> block object
private static final ObjectArray<Block> BLOCK_STATE_MAP = new ObjectArray<>();
private static final ObjectArray<Block> BLOCK_STATE_MAP = ObjectArray.singleThread();
// Block id -> valid property keys (order is important for lookup)
private static final ObjectArray<PropertyType[]> PROPERTIES_TYPE = new ObjectArray<>();
private static final ObjectArray<PropertyType[]> PROPERTIES_TYPE = ObjectArray.singleThread();
// Block id -> Map<PropertiesValues, Block>
private static final ObjectArray<Map<PropertiesHolder, BlockImpl>> POSSIBLE_STATES = new ObjectArray<>();
private static final ObjectArray<Map<PropertiesHolder, BlockImpl>> POSSIBLE_STATES = ObjectArray.singleThread();
private static final Registry.Container<Block> CONTAINER = Registry.createContainer(Registry.Resource.BLOCKS,
(namespace, properties) -> {
final int blockId = properties.getInt("id");

View File

@ -6,8 +6,8 @@ import net.minestom.server.network.packet.client.login.LoginStartPacket;
import net.minestom.server.network.packet.client.play.*;
import net.minestom.server.network.packet.client.status.PingPacket;
import net.minestom.server.network.packet.client.status.StatusRequestPacket;
import net.minestom.server.utils.collection.ObjectArray;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.collection.ObjectArray;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.UnknownNullability;
@ -19,7 +19,7 @@ import java.util.function.Function;
* Packets are registered using {@link #register(int, Function)} and created using {@link #create(int, BinaryReader)}.
*/
public sealed class ClientPacketsHandler permits ClientPacketsHandler.Status, ClientPacketsHandler.Login, ClientPacketsHandler.Play {
private final ObjectArray<Function<BinaryReader, ClientPacket>> suppliers = new ObjectArray<>(0x10);
private final ObjectArray<Function<BinaryReader, ClientPacket>> suppliers = ObjectArray.singleThread(0x10);
private ClientPacketsHandler() {
}

View File

@ -73,7 +73,7 @@ public final class Registry {
public static <T extends ProtocolObject> Container<T> createContainer(Resource resource, Container.Loader<T> loader) {
var entries = Registry.load(resource);
Map<String, T> namespaces = new HashMap<>(entries.size());
ObjectArray<T> ids = new ObjectArray<>(entries.size());
ObjectArray<T> ids = ObjectArray.singleThread(entries.size());
for (var entry : entries.entrySet()) {
final String namespace = entry.getKey();
final Properties properties = Properties.fromMap(entry.getValue());

View File

@ -1,46 +1,41 @@
package net.minestom.server.utils.collection;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.UnknownNullability;
import java.util.Arrays;
/**
* Represents an array which will be resized to the highest required index.
*
* @param <T> the type of the array
*/
@ApiStatus.Internal
public final class ObjectArray<T> {
private T[] array;
private int max;
public ObjectArray(int size) {
//noinspection unchecked
this.array = (T[]) new Object[size];
public sealed interface ObjectArray<T>
permits ObjectArrayImpl.SingleThread, ObjectArrayImpl.Concurrent {
static <T> @NotNull ObjectArray<T> singleThread(int initialSize) {
return new ObjectArrayImpl.SingleThread<>(initialSize);
}
public ObjectArray() {
this(0);
static <T> @NotNull ObjectArray<T> singleThread() {
return singleThread(0);
}
public void set(int index, @Nullable T object) {
T[] array = this.array;
if (index >= array.length) {
final int newLength = index * 2 + 1;
this.array = array = Arrays.copyOf(array, newLength);
}
array[index] = object;
this.max = Math.max(max, index);
static <T> @NotNull ObjectArray<T> concurrent(int initialSize) {
return new ObjectArrayImpl.Concurrent<>(initialSize);
}
public @UnknownNullability T get(int index) {
final T[] array = this.array;
return index < array.length ? array[index] : null;
static <T> @NotNull ObjectArray<T> concurrent() {
return concurrent(0);
}
public void trim() {
this.array = Arrays.copyOf(array, max + 1);
@UnknownNullability T get(int index);
void set(int index, @Nullable T object);
default void remove(int index) {
set(index, null);
}
void trim();
}

View File

@ -0,0 +1,72 @@
package net.minestom.server.utils.collection;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.UnknownNullability;
import java.util.Arrays;
final class ObjectArrayImpl {
static final class SingleThread<T> implements ObjectArray<T> {
private T[] array;
private int max;
SingleThread(int size) {
//noinspection unchecked
this.array = (T[]) new Object[size];
}
@Override
public @UnknownNullability T get(int index) {
final T[] array = this.array;
return index < array.length ? array[index] : null;
}
@Override
public void set(int index, @Nullable T object) {
T[] array = this.array;
if (index >= array.length) {
final int newLength = index * 2 + 1;
this.array = array = Arrays.copyOf(array, newLength);
}
array[index] = object;
this.max = Math.max(max, index);
}
@Override
public void trim() {
this.array = Arrays.copyOf(array, max + 1);
}
}
static final class Concurrent<T> implements ObjectArray<T> {
private volatile T[] array;
private int max;
Concurrent(int size) {
//noinspection unchecked
this.array = (T[]) new Object[size];
}
@Override
public @UnknownNullability T get(int index) {
final T[] array = this.array;
return index < array.length ? array[index] : null;
}
@Override
public synchronized void set(int index, @Nullable T object) {
T[] array = this.array;
if (index >= array.length) {
final int newLength = index * 2 + 1;
this.array = array = Arrays.copyOf(array, newLength);
}
array[index] = object;
this.max = Math.max(max, index);
}
@Override
public synchronized void trim() {
this.array = Arrays.copyOf(array, max + 1);
}
}
}

View File

@ -1,15 +1,17 @@
package net.minestom.server.utils.collection;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
public class ObjectArrayTest {
@Test
public void testArray() {
ObjectArray<String> array = new ObjectArray<>();
@ParameterizedTest
@ValueSource(booleans = {false, true})
public void testArray(boolean concurrent) {
ObjectArray<String> array = concurrent ? ObjectArray.concurrent() : ObjectArray.singleThread();
array.set(50, "Hey");
assertEquals("Hey", array.get(50));