Remove AcquirableImpl.java, more comment

This commit is contained in:
TheMode 2021-04-18 16:50:06 +02:00
parent e63dbf28db
commit bd9cab5805
4 changed files with 54 additions and 49 deletions

View File

@ -23,7 +23,6 @@ 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.AcquirableImpl;
import net.minestom.server.lock.LockedElement;
import net.minestom.server.network.packet.server.play.*;
import net.minestom.server.network.player.PlayerConnection;
@ -126,7 +125,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 AcquirableImpl<>(this);
private final Acquirable<Entity> acquirable = new Acquirable<>(this);
/**
* Lock used to support #switchEntityType

View File

@ -13,32 +13,37 @@ import java.util.function.Consumer;
/**
* Represents an element which can be acquired.
* Used for synchronization purpose.
* <p>
* Implementations of this class are recommended to be immutable (or at least thread-safe).
* The default one is {@link AcquirableImpl}.
*
* @param <T> the acquirable object type
*/
public interface Acquirable<T> {
public class Acquirable<T> {
ThreadLocal<Collection<Entity>> CURRENT_ENTITIES = ThreadLocal.withInitial(Collections::emptyList);
public static final ThreadLocal<Collection<Entity>> CURRENT_ENTITIES = ThreadLocal.withInitial(Collections::emptyList);
static @NotNull Collection<@NotNull Entity> currentEntities() {
public static @NotNull Collection<@NotNull Entity> currentEntities() {
return CURRENT_ENTITIES.get();
}
@ApiStatus.Internal
static void refreshEntities(@NotNull Collection<@NotNull Entity> entities) {
public static void refreshEntities(@NotNull Collection<@NotNull Entity> entities) {
CURRENT_ENTITIES.set(entities);
}
private final T value;
private final Handler handler;
public Acquirable(@NotNull T value) {
this.value = value;
this.handler = new Handler();
}
/**
* Blocks the current thread until 'this' can be acquired,
* and execute {@code consumer} as a callback with the acquired object.
*
* @param consumer the acquisition consumer
*/
default void acquire(@NotNull Consumer<@NotNull T> consumer) {
public void acquire(@NotNull Consumer<@NotNull T> consumer) {
final Thread currentThread = Thread.currentThread();
final BatchThread elementThread = getHandler().getBatchThread();
Acquisition.acquire(currentThread, elementThread, () -> consumer.accept(unwrap()));
@ -52,7 +57,7 @@ public interface Acquirable<T> {
* @return true if the acquisition happened without synchronization,
* false otherwise
*/
default boolean tryAcquire(@NotNull Consumer<@NotNull T> consumer) {
public boolean tryAcquire(@NotNull Consumer<@NotNull T> consumer) {
final Thread currentThread = Thread.currentThread();
final BatchThread elementThread = getHandler().getBatchThread();
if (elementThread == null || elementThread == currentThread) {
@ -69,15 +74,32 @@ public interface Acquirable<T> {
*
* @param consumer the consumer of the acquired object
*/
default void scheduledAcquire(@NotNull Consumer<T> consumer) {
public void scheduledAcquire(@NotNull Consumer<T> consumer) {
Acquisition.scheduledAcquireRequest(this, consumer);
}
@NotNull T unwrap();
/**
* Unwrap the contained object unsafely.
* <p>
* Should only be considered when thread-safety is not necessary (e.g. comparing positions)
*
* @return the unwraped value
*/
public @NotNull T unwrap() {
return value;
}
@NotNull Handler getHandler();
/**
* Gets the {@link Handler} of this acquirable element,
* containing the currently linked thread.
*
* @return this element handler
*/
public @NotNull Handler getHandler() {
return handler;
}
class Handler {
public static class Handler {
private volatile ThreadProvider.ChunkEntry chunkEntry;

View File

@ -1,33 +0,0 @@
package net.minestom.server.lock;
import org.jetbrains.annotations.NotNull;
/**
* Basic implementation of {@link Acquirable}.
* <p>
* Class is immutable.
*
* @param <T> the object type which can be acquired
*/
public class AcquirableImpl<T> implements Acquirable<T> {
private final T value;
private final Handler handler;
public AcquirableImpl(@NotNull T value) {
this.value = value;
this.handler = new Handler();
}
@NotNull
@Override
public T unwrap() {
return value;
}
@NotNull
@Override
public Handler getHandler() {
return handler;
}
}

View File

@ -14,10 +14,23 @@ public final class Acquisition {
private static final ThreadLocal<ScheduledAcquisition> SCHEDULED_ACQUISITION = ThreadLocal.withInitial(ScheduledAcquisition::new);
/**
* Global lock used for synchronization.
*/
private static final Monitor GLOBAL_MONITOR = new Monitor();
private static final AtomicLong WAIT_COUNTER_NANO = new AtomicLong();
/**
* Acquires a {@link Collection}.
* <p>
* Order is not guaranteed.
*
* @param collection the collection to acquire
* @param consumer the consumer called for each of the collection element
* @param <E> the object type
* @param <T> the acquirable object
*/
public static <E, T extends Acquirable<E>> void acquireForEach(@NotNull Collection<? super T> collection,
@NotNull Consumer<? super E> consumer) {
final Thread currentThread = Thread.currentThread();
@ -65,7 +78,8 @@ public final class Acquisition {
/**
* Ensures that {@code callback} is safely executed inside the batch thread.
*/
protected static void acquire(@NotNull Thread currentThread, @Nullable BatchThread elementThread, Runnable callback) {
protected static void acquire(@NotNull Thread currentThread, @Nullable BatchThread elementThread,
@NotNull Runnable callback) {
if (elementThread == null || elementThread == currentThread) {
callback.run();
} else {
@ -119,6 +133,9 @@ public final class Acquisition {
private static <E, T extends Acquirable<E>> Map<BatchThread, List<E>> retrieveThreadMap(@NotNull Collection<? super T> collection,
@NotNull Thread currentThread,
@NotNull Consumer<? super E> 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 (Object obj : collection) {
T element = (T) obj;