mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-20 23:21:24 +01:00
Remove generic Acquirable
This commit is contained in:
parent
86faa435f7
commit
297652c610
@ -4,7 +4,7 @@ import com.google.common.collect.Queues;
|
||||
import net.minestom.server.instance.Chunk;
|
||||
import net.minestom.server.instance.Instance;
|
||||
import net.minestom.server.instance.InstanceManager;
|
||||
import net.minestom.server.lock.Acquisition;
|
||||
import net.minestom.server.entity.acquirable.Acquisition;
|
||||
import net.minestom.server.monitoring.TickMonitor;
|
||||
import net.minestom.server.network.ConnectionManager;
|
||||
import net.minestom.server.network.player.NettyPlayerConnection;
|
||||
|
@ -13,6 +13,7 @@ import net.minestom.server.collision.BoundingBox;
|
||||
import net.minestom.server.collision.CollisionUtils;
|
||||
import net.minestom.server.data.Data;
|
||||
import net.minestom.server.data.DataContainer;
|
||||
import net.minestom.server.entity.acquirable.AcquirableEntity;
|
||||
import net.minestom.server.entity.metadata.EntityMeta;
|
||||
import net.minestom.server.event.Event;
|
||||
import net.minestom.server.event.EventCallback;
|
||||
@ -22,8 +23,6 @@ import net.minestom.server.instance.Chunk;
|
||||
import net.minestom.server.instance.Instance;
|
||||
import net.minestom.server.instance.InstanceManager;
|
||||
import net.minestom.server.instance.block.CustomBlock;
|
||||
import net.minestom.server.lock.Acquirable;
|
||||
import net.minestom.server.lock.LockedElement;
|
||||
import net.minestom.server.network.packet.server.play.*;
|
||||
import net.minestom.server.network.player.PlayerConnection;
|
||||
import net.minestom.server.permission.Permission;
|
||||
@ -60,7 +59,7 @@ import java.util.function.UnaryOperator;
|
||||
* <p>
|
||||
* To create your own entity you probably want to extends {@link LivingEntity} or {@link EntityCreature} instead.
|
||||
*/
|
||||
public class Entity implements Viewable, Tickable, LockedElement, EventHandler, DataContainer, PermissionHandler, HoverEventSource<ShowEntity> {
|
||||
public class Entity implements Viewable, Tickable, EventHandler, DataContainer, PermissionHandler, HoverEventSource<ShowEntity> {
|
||||
|
||||
private static final Map<Integer, Entity> ENTITY_BY_ID = new ConcurrentHashMap<>();
|
||||
private static final Map<UUID, Entity> ENTITY_BY_UUID = new ConcurrentHashMap<>();
|
||||
@ -125,7 +124,7 @@ public class Entity implements Viewable, Tickable, LockedElement, EventHandler,
|
||||
private long ticks;
|
||||
private final EntityTickEvent tickEvent = new EntityTickEvent(this);
|
||||
|
||||
private final Acquirable<Entity> acquirable = new Acquirable<>(this);
|
||||
private final AcquirableEntity acquirableEntity = new AcquirableEntity(this);
|
||||
|
||||
/**
|
||||
* Lock used to support #switchEntityType
|
||||
@ -1567,9 +1566,8 @@ public class Entity implements Viewable, Tickable, LockedElement, EventHandler,
|
||||
return Objects.requireNonNullElse(this.customSynchronizationCooldown, SYNCHRONIZATION_COOLDOWN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull <T> Acquirable<T> getAcquiredElement() {
|
||||
return (Acquirable<T>) acquirable;
|
||||
public @NotNull AcquirableEntity getAcquirable() {
|
||||
return acquirableEntity;
|
||||
}
|
||||
|
||||
public enum Pose {
|
||||
|
@ -44,7 +44,6 @@ import net.minestom.server.item.ItemStack;
|
||||
import net.minestom.server.item.Material;
|
||||
import net.minestom.server.item.metadata.WrittenBookMeta;
|
||||
import net.minestom.server.listener.PlayerDiggingListener;
|
||||
import net.minestom.server.lock.Acquirable;
|
||||
import net.minestom.server.network.ConnectionManager;
|
||||
import net.minestom.server.network.ConnectionState;
|
||||
import net.minestom.server.network.PlayerProvider;
|
||||
|
@ -0,0 +1,25 @@
|
||||
package net.minestom.server.entity.acquirable;
|
||||
|
||||
import net.minestom.server.entity.Entity;
|
||||
import net.minestom.server.utils.collection.CollectionView;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class AcquirableCollection<E extends Entity> extends CollectionView<E, AcquirableEntity> {
|
||||
|
||||
private final Collection<AcquirableEntity> acquirableEntityCollection;
|
||||
|
||||
public AcquirableCollection(@NotNull Collection<AcquirableEntity> acquirableEntityCollection) {
|
||||
super(acquirableEntityCollection,
|
||||
Entity::getAcquirable,
|
||||
acquirableEntity -> (E) acquirableEntity.unwrap());
|
||||
this.acquirableEntityCollection = acquirableEntityCollection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEach(Consumer<? super E> action) {
|
||||
// Acquisition.acquireForEach(acquirableEntityCollection, action);
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package net.minestom.server.lock;
|
||||
package net.minestom.server.entity.acquirable;
|
||||
|
||||
import net.minestom.server.entity.Entity;
|
||||
import net.minestom.server.thread.BatchThread;
|
||||
@ -15,10 +15,8 @@ import java.util.function.Consumer;
|
||||
/**
|
||||
* Represents an element which can be acquired.
|
||||
* Used for synchronization purpose.
|
||||
*
|
||||
* @param <T> the acquirable object type
|
||||
*/
|
||||
public final class Acquirable<T> {
|
||||
public final class AcquirableEntity {
|
||||
|
||||
public static final ThreadLocal<Collection<Entity>> CURRENT_ENTITIES = ThreadLocal.withInitial(Collections::emptyList);
|
||||
|
||||
@ -46,11 +44,11 @@ public final class Acquirable<T> {
|
||||
CURRENT_ENTITIES.set(entities);
|
||||
}
|
||||
|
||||
private final T value;
|
||||
private final Entity entity;
|
||||
private final Handler handler;
|
||||
|
||||
public Acquirable(@NotNull T value) {
|
||||
this.value = value;
|
||||
public AcquirableEntity(@NotNull Entity entity) {
|
||||
this.entity = entity;
|
||||
this.handler = new Handler();
|
||||
}
|
||||
|
||||
@ -60,7 +58,7 @@ public final class Acquirable<T> {
|
||||
*
|
||||
* @param consumer the acquisition consumer
|
||||
*/
|
||||
public void acquire(@NotNull Consumer<@NotNull T> consumer) {
|
||||
public void acquire(@NotNull Consumer<@NotNull Entity> consumer) {
|
||||
final Thread currentThread = Thread.currentThread();
|
||||
final BatchThread elementThread = getHandler().getBatchThread();
|
||||
Acquisition.acquire(currentThread, elementThread, () -> consumer.accept(unwrap()));
|
||||
@ -74,7 +72,7 @@ public final class Acquirable<T> {
|
||||
* @return true if the acquisition happened without synchronization,
|
||||
* false otherwise
|
||||
*/
|
||||
public boolean tryAcquire(@NotNull Consumer<@NotNull T> consumer) {
|
||||
public boolean tryAcquire(@NotNull Consumer<@NotNull Entity> consumer) {
|
||||
final Thread currentThread = Thread.currentThread();
|
||||
final BatchThread elementThread = getHandler().getBatchThread();
|
||||
if (Objects.equals(currentThread, elementThread)) {
|
||||
@ -90,7 +88,7 @@ public final class Acquirable<T> {
|
||||
*
|
||||
* @return this element or null if unsafe
|
||||
*/
|
||||
public @Nullable T tryAcquire() {
|
||||
public @Nullable Entity tryAcquire() {
|
||||
final Thread currentThread = Thread.currentThread();
|
||||
final BatchThread elementThread = getHandler().getBatchThread();
|
||||
if (Objects.equals(currentThread, elementThread)) {
|
||||
@ -106,7 +104,7 @@ public final class Acquirable<T> {
|
||||
*
|
||||
* @param consumer the consumer of the acquired object
|
||||
*/
|
||||
public void scheduledAcquire(@NotNull Consumer<T> consumer) {
|
||||
public void scheduledAcquire(@NotNull Consumer<Entity> consumer) {
|
||||
Acquisition.scheduledAcquireRequest(this, consumer);
|
||||
}
|
||||
|
||||
@ -117,8 +115,8 @@ public final class Acquirable<T> {
|
||||
*
|
||||
* @return the unwraped value
|
||||
*/
|
||||
public @NotNull T unwrap() {
|
||||
return value;
|
||||
public @NotNull Entity unwrap() {
|
||||
return entity;
|
||||
}
|
||||
|
||||
/**
|
@ -1,5 +1,6 @@
|
||||
package net.minestom.server.lock;
|
||||
package net.minestom.server.entity.acquirable;
|
||||
|
||||
import net.minestom.server.entity.Entity;
|
||||
import net.minestom.server.thread.BatchThread;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@ -27,22 +28,21 @@ public final class Acquisition {
|
||||
*
|
||||
* @param collection the collection to acquire
|
||||
* @param consumer the consumer called for each of the collection element
|
||||
* @param <E> the object type
|
||||
*/
|
||||
public static <E> void acquireForEach(@NotNull Collection<Acquirable<E>> collection,
|
||||
@NotNull Consumer<? super E> consumer) {
|
||||
public static void acquireForEach(@NotNull Collection<AcquirableEntity> collection,
|
||||
@NotNull Consumer<Entity> consumer) {
|
||||
final Thread currentThread = Thread.currentThread();
|
||||
Map<BatchThread, List<E>> threadCacheMap = retrieveOptionalThreadMap(collection, currentThread, consumer);
|
||||
Map<BatchThread, List<Entity>> threadCacheMap = retrieveOptionalThreadMap(collection, currentThread, consumer);
|
||||
|
||||
// Acquire all the threads one by one
|
||||
{
|
||||
for (Map.Entry<BatchThread, List<E>> entry : threadCacheMap.entrySet()) {
|
||||
for (Map.Entry<BatchThread, List<Entity>> entry : threadCacheMap.entrySet()) {
|
||||
final BatchThread batchThread = entry.getKey();
|
||||
final List<E> elements = entry.getValue();
|
||||
final List<Entity> entities = entry.getValue();
|
||||
|
||||
acquire(currentThread, batchThread, () -> {
|
||||
for (E element : elements) {
|
||||
consumer.accept(element);
|
||||
for (Entity entity : entities) {
|
||||
consumer.accept(entity);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -55,20 +55,20 @@ public final class Acquisition {
|
||||
public static void processThreadTick() {
|
||||
ScheduledAcquisition scheduledAcquisition = SCHEDULED_ACQUISITION.get();
|
||||
|
||||
final List<Acquirable<Object>> acquirableElements = scheduledAcquisition.acquirableElements;
|
||||
final List<AcquirableEntity> acquirableEntityElements = scheduledAcquisition.acquirableEntityElements;
|
||||
|
||||
if (!acquirableElements.isEmpty()) {
|
||||
final Map<Object, List<Consumer<Object>>> callbacks = scheduledAcquisition.callbacks;
|
||||
if (!acquirableEntityElements.isEmpty()) {
|
||||
final Map<Object, List<Consumer<Entity>>> callbacks = scheduledAcquisition.callbacks;
|
||||
|
||||
acquireForEach(acquirableElements, element -> {
|
||||
List<Consumer<Object>> consumers = callbacks.get(element);
|
||||
acquireForEach(acquirableEntityElements, element -> {
|
||||
List<Consumer<Entity>> consumers = callbacks.get(element);
|
||||
if (consumers == null || consumers.isEmpty())
|
||||
return;
|
||||
consumers.forEach(objectConsumer -> objectConsumer.accept(element));
|
||||
});
|
||||
|
||||
// Clear collections..
|
||||
acquirableElements.clear();
|
||||
acquirableEntityElements.clear();
|
||||
callbacks.clear();
|
||||
}
|
||||
}
|
||||
@ -129,12 +129,12 @@ public final class Acquisition {
|
||||
GLOBAL_LOCK.unlock();
|
||||
}
|
||||
|
||||
protected synchronized static <T> void scheduledAcquireRequest(@NotNull Acquirable<T> acquirable, Consumer<T> consumer) {
|
||||
protected synchronized static void scheduledAcquireRequest(@NotNull AcquirableEntity acquirableEntity, Consumer<Entity> consumer) {
|
||||
ScheduledAcquisition scheduledAcquisition = SCHEDULED_ACQUISITION.get();
|
||||
scheduledAcquisition.acquirableElements.add((Acquirable<Object>) acquirable);
|
||||
scheduledAcquisition.acquirableEntityElements.add(acquirableEntity);
|
||||
scheduledAcquisition.callbacks
|
||||
.computeIfAbsent(acquirable.unwrap(), objectAcquirable -> new ArrayList<>())
|
||||
.add((Consumer<Object>) consumer);
|
||||
.computeIfAbsent(acquirableEntity.unwrap(), objectAcquirable -> new ArrayList<>())
|
||||
.add(consumer);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -143,18 +143,17 @@ public final class Acquisition {
|
||||
* @param collection the acquirable collection
|
||||
* @param currentThread the current thread
|
||||
* @param consumer the consumer to execute when an element is already in the current thread
|
||||
* @param <E> the acquirable element type
|
||||
* @return a new Thread to acquirable elements map
|
||||
*/
|
||||
protected static <E> Map<BatchThread, List<E>> retrieveOptionalThreadMap(@NotNull Collection<Acquirable<E>> collection,
|
||||
protected static Map<BatchThread, List<Entity>> retrieveOptionalThreadMap(@NotNull Collection<AcquirableEntity> collection,
|
||||
@NotNull Thread currentThread,
|
||||
@NotNull Consumer<? super E> consumer) {
|
||||
@NotNull Consumer<? super Entity> consumer) {
|
||||
// Separate a collection of acquirable elements into a map of thread->elements
|
||||
// Useful to reduce the number of acquisition
|
||||
|
||||
Map<BatchThread, List<E>> threadCacheMap = new HashMap<>();
|
||||
for (Acquirable<E> element : collection) {
|
||||
final E value = element.unwrap();
|
||||
Map<BatchThread, List<Entity>> threadCacheMap = new HashMap<>();
|
||||
for (AcquirableEntity element : collection) {
|
||||
final Entity value = element.unwrap();
|
||||
|
||||
final BatchThread elementThread = element.getHandler().getBatchThread();
|
||||
if (currentThread == elementThread) {
|
||||
@ -162,7 +161,7 @@ public final class Acquisition {
|
||||
consumer.accept(value);
|
||||
} else {
|
||||
// The element is manager in a different thread, cache it
|
||||
List<E> threadCacheList = threadCacheMap.computeIfAbsent(elementThread, batchThread -> new ArrayList<>());
|
||||
List<Entity> threadCacheList = threadCacheMap.computeIfAbsent(elementThread, batchThread -> new ArrayList<>());
|
||||
threadCacheList.add(value);
|
||||
}
|
||||
}
|
||||
@ -170,16 +169,16 @@ public final class Acquisition {
|
||||
return threadCacheMap;
|
||||
}
|
||||
|
||||
protected static <E> Map<BatchThread, List<E>> retrieveThreadMap(@NotNull Collection<Acquirable<E>> collection) {
|
||||
protected static Map<BatchThread, List<Entity>> retrieveThreadMap(@NotNull Collection<AcquirableEntity> collection) {
|
||||
// Separate a collection of acquirable elements into a map of thread->elements
|
||||
// Useful to reduce the number of acquisition
|
||||
Map<BatchThread, List<E>> threadCacheMap = new HashMap<>();
|
||||
for (Acquirable<E> element : collection) {
|
||||
final E value = element.unwrap();
|
||||
final BatchThread elementThread = element.getHandler().getBatchThread();
|
||||
Map<BatchThread, List<Entity>> threadCacheMap = new HashMap<>();
|
||||
for (AcquirableEntity acquirableEntity : collection) {
|
||||
final Entity entity = acquirableEntity.unwrap();
|
||||
final BatchThread elementThread = acquirableEntity.getHandler().getBatchThread();
|
||||
|
||||
List<E> threadCacheList = threadCacheMap.computeIfAbsent(elementThread, batchThread -> new ArrayList<>());
|
||||
threadCacheList.add(value);
|
||||
List<Entity> threadCacheList = threadCacheMap.computeIfAbsent(elementThread, batchThread -> new ArrayList<>());
|
||||
threadCacheList.add(entity);
|
||||
}
|
||||
|
||||
return threadCacheMap;
|
||||
@ -194,7 +193,7 @@ public final class Acquisition {
|
||||
}
|
||||
|
||||
private static class ScheduledAcquisition {
|
||||
private final List<Acquirable<Object>> acquirableElements = new ArrayList<>();
|
||||
private final Map<Object, List<Consumer<Object>>> callbacks = new HashMap<>();
|
||||
private final List<AcquirableEntity> acquirableEntityElements = new ArrayList<>();
|
||||
private final Map<Object, List<Consumer<Entity>>> callbacks = new HashMap<>();
|
||||
}
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
package net.minestom.server.lock;
|
||||
|
||||
import net.minestom.server.utils.collection.CollectionView;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class AcquirableCollection<E extends LockedElement> extends CollectionView<E, Acquirable<E>> {
|
||||
|
||||
private final Collection<Acquirable<E>> acquirableCollection;
|
||||
|
||||
public AcquirableCollection(@NotNull Collection<Acquirable<E>> acquirableCollection) {
|
||||
super(acquirableCollection,
|
||||
LockedElement::getAcquiredElement,
|
||||
Acquirable::unwrap);
|
||||
this.acquirableCollection = acquirableCollection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEach(Consumer<? super E> action) {
|
||||
Acquisition.acquireForEach(acquirableCollection, action);
|
||||
}
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
package net.minestom.server.lock;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Represents an element that have a {@link Acquirable} linked to it.
|
||||
* <p>
|
||||
* Useful if you want to provide an access point to an object without risking to compromise
|
||||
* the thread-safety of your code.
|
||||
*/
|
||||
public interface LockedElement {
|
||||
|
||||
/**
|
||||
* Gets the {@link Acquirable} of this locked element.
|
||||
* <p>
|
||||
* Should be a constant.
|
||||
*
|
||||
* @return the acquirable element linked to this object
|
||||
*/
|
||||
<T> @NotNull Acquirable<T> getAcquiredElement();
|
||||
|
||||
}
|
@ -2,11 +2,11 @@ package net.minestom.server.thread;
|
||||
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.entity.Entity;
|
||||
import net.minestom.server.entity.acquirable.AcquirableEntity;
|
||||
import net.minestom.server.instance.Chunk;
|
||||
import net.minestom.server.instance.Instance;
|
||||
import net.minestom.server.instance.InstanceContainer;
|
||||
import net.minestom.server.instance.SharedInstance;
|
||||
import net.minestom.server.lock.Acquirable;
|
||||
import net.minestom.server.utils.MathUtils;
|
||||
import net.minestom.server.utils.chunk.ChunkUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@ -148,7 +148,7 @@ public abstract class ThreadProvider {
|
||||
final var entities = entitiesList.stream()
|
||||
.flatMap(Collection::stream)
|
||||
.collect(Collectors.toList());
|
||||
Acquirable.refreshEntities(Collections.unmodifiableList(entities));
|
||||
AcquirableEntity.refreshEntities(Collections.unmodifiableList(entities));
|
||||
|
||||
final ReentrantLock lock = thread.getLock();
|
||||
lock.lock();
|
||||
@ -177,8 +177,8 @@ public abstract class ThreadProvider {
|
||||
// Clear removed entities
|
||||
{
|
||||
for (Entity entity : removedEntities) {
|
||||
Acquirable<Entity> acquirable = entity.getAcquiredElement();
|
||||
ChunkEntry chunkEntry = acquirable.getHandler().getChunkEntry();
|
||||
AcquirableEntity acquirableEntity = entity.getAcquirable();
|
||||
ChunkEntry chunkEntry = acquirableEntity.getHandler().getChunkEntry();
|
||||
// Remove from list
|
||||
if (chunkEntry != null) {
|
||||
chunkEntry.entities.remove(entity);
|
||||
@ -242,8 +242,8 @@ public abstract class ThreadProvider {
|
||||
private void refreshEntitiesThread(Instance instance, Chunk chunk) {
|
||||
var entities = instance.getChunkEntities(chunk);
|
||||
for (Entity entity : entities) {
|
||||
Acquirable<Entity> acquirable = entity.getAcquiredElement();
|
||||
ChunkEntry handlerChunkEntry = acquirable.getHandler().getChunkEntry();
|
||||
AcquirableEntity acquirableEntity = entity.getAcquirable();
|
||||
ChunkEntry handlerChunkEntry = acquirableEntity.getHandler().getChunkEntry();
|
||||
Chunk batchChunk = handlerChunkEntry != null ? handlerChunkEntry.getChunk() : null;
|
||||
|
||||
Chunk entityChunk = entity.getChunk();
|
||||
@ -262,7 +262,7 @@ public abstract class ThreadProvider {
|
||||
ChunkEntry chunkEntry = chunkEntryMap.get(entityChunk);
|
||||
if (chunkEntry != null) {
|
||||
chunkEntry.entities.add(entity);
|
||||
acquirable.getHandler().refreshChunkEntry(chunkEntry);
|
||||
acquirableEntity.getHandler().refreshChunkEntry(chunkEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user