Put implementation detail in AcquirableImpl

This commit is contained in:
TheMode 2021-04-25 20:00:03 +02:00
parent b47946bfed
commit 6c3c6e1438
4 changed files with 62 additions and 53 deletions

View File

@ -84,12 +84,11 @@ public interface Acquirable<T> {
default @NotNull Acquired<T> lock() {
var optional = local();
if (optional.isPresent()) {
return new Acquired<>(optional.get(), false, null);
return Acquired.local(optional.get());
} else {
final Thread currentThread = Thread.currentThread();
final TickThread tickThread = getHandler().getTickThread();
var lock = Acquired.acquireEnter(currentThread, tickThread);
return new Acquired<>(unwrap(), true, lock);
return Acquired.locked(unwrap(), currentThread, tickThread);
}
}

View File

@ -26,11 +26,11 @@ public class AcquirableCollection<E> implements Collection<Acquirable<E>> {
final TickThread tickThread = entry.getKey();
final List<E> values = entry.getValue();
var lock = Acquired.acquireEnter(currentThread, tickThread);
var lock = AcquirableImpl.enter(currentThread, tickThread);
for (E value : values) {
consumer.accept(value);
}
Acquired.acquireLeave(lock);
AcquirableImpl.leave(lock);
}
}
}

View File

@ -1,9 +1,12 @@
package net.minestom.server.acquirable;
import net.minestom.server.entity.Entity;
import net.minestom.server.thread.TickThread;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Stream;
class AcquirableImpl<T> implements Acquirable<T> {
@ -11,6 +14,11 @@ class AcquirableImpl<T> implements Acquirable<T> {
protected static final ThreadLocal<Stream<Entity>> CURRENT_ENTITIES = ThreadLocal.withInitial(Stream::empty);
protected static final AtomicLong WAIT_COUNTER_NANO = new AtomicLong();
/**
* Global lock used for synchronization.
*/
private static final ReentrantLock GLOBAL_LOCK = new ReentrantLock();
private final T value;
private final Acquirable.Handler handler;
@ -28,4 +36,42 @@ class AcquirableImpl<T> implements Acquirable<T> {
public @NotNull Acquirable.Handler getHandler() {
return handler;
}
protected static @Nullable ReentrantLock enter(@Nullable Thread currentThread, @Nullable TickThread elementThread) {
// Monitoring
long time = System.nanoTime();
ReentrantLock currentLock;
{
final TickThread current = currentThread instanceof TickThread ?
(TickThread) currentThread : null;
currentLock = current != null && current.getLock().isHeldByCurrentThread() ?
current.getLock() : null;
}
if (currentLock != null)
currentLock.unlock();
GLOBAL_LOCK.lock();
if (currentLock != null)
currentLock.lock();
final var lock = elementThread != null ? elementThread.getLock() : null;
final boolean acquired = lock == null || lock.isHeldByCurrentThread();
if (!acquired) {
lock.lock();
}
// Monitoring
AcquirableImpl.WAIT_COUNTER_NANO.addAndGet(System.nanoTime() - time);
return !acquired ? lock : null;
}
protected static void leave(@Nullable ReentrantLock lock) {
if (lock != null) {
lock.unlock();
}
GLOBAL_LOCK.unlock();
}
}

View File

@ -3,17 +3,11 @@ package net.minestom.server.acquirable;
import net.minestom.server.thread.TickThread;
import net.minestom.server.utils.validate.Check;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.concurrent.locks.ReentrantLock;
public class Acquired<T> {
/**
* Global lock used for synchronization.
*/
private static final ReentrantLock GLOBAL_LOCK = new ReentrantLock();
private final T value;
private final boolean locked;
@ -21,11 +15,19 @@ public class Acquired<T> {
private boolean unlocked;
protected Acquired(@NotNull T value,
boolean locked, @Nullable ReentrantLock lock) {
protected static <T> Acquired<T> local(@NotNull T value) {
return new Acquired<>(value, false, null, null);
}
protected static <T> Acquired<T> locked(@NotNull T value, Thread currentThread, TickThread tickThread) {
return new Acquired<>(value, true, currentThread, tickThread);
}
private Acquired(@NotNull T value,
boolean locked, Thread currentThread, TickThread tickThread) {
this.value = value;
this.locked = locked;
this.lock = lock;
this.lock = locked ? AcquirableImpl.enter(currentThread, tickThread) : null;
}
public @NotNull T get() {
@ -38,45 +40,7 @@ public class Acquired<T> {
this.unlocked = true;
if (!locked)
return;
acquireLeave(lock);
}
protected static @Nullable ReentrantLock acquireEnter(@Nullable Thread currentThread, @Nullable TickThread elementThread) {
// Monitoring
long time = System.nanoTime();
ReentrantLock currentLock;
{
final TickThread current = currentThread instanceof TickThread ?
(TickThread) currentThread : null;
currentLock = current != null && current.getLock().isHeldByCurrentThread() ?
current.getLock() : null;
}
if (currentLock != null)
currentLock.unlock();
GLOBAL_LOCK.lock();
if (currentLock != null)
currentLock.lock();
final var lock = elementThread != null ? elementThread.getLock() : null;
final boolean acquired = lock == null || lock.isHeldByCurrentThread();
if (!acquired) {
lock.lock();
}
// Monitoring
AcquirableImpl.WAIT_COUNTER_NANO.addAndGet(System.nanoTime() - time);
return !acquired ? lock : null;
}
protected static void acquireLeave(@Nullable ReentrantLock lock) {
if (lock != null) {
lock.unlock();
}
GLOBAL_LOCK.unlock();
AcquirableImpl.leave(lock);
}
private void checkLock() {