net.minestom.server.thread.AcquirableCollection Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of minestom-snapshots Show documentation
Show all versions of minestom-snapshots Show documentation
1.20.4 Lightweight Minecraft server
package net.minestom.server.thread;
import net.minestom.server.utils.async.AsyncUtils;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import java.util.*;
import java.util.function.Consumer;
import java.util.stream.Stream;
@ApiStatus.Experimental
public class AcquirableCollection implements Collection> {
private final Collection> acquirableCollection;
public AcquirableCollection(Collection> acquirableCollection) {
this.acquirableCollection = acquirableCollection;
}
public void acquireSync(@NotNull Consumer consumer) {
final Thread currentThread = Thread.currentThread();
var threadEntitiesMap = retrieveOptionalThreadMap(acquirableCollection, currentThread, consumer);
// Acquire all the threads one by one
{
for (var entry : threadEntitiesMap.entrySet()) {
final TickThread tickThread = entry.getKey();
final List values = entry.getValue();
var lock = AcquirableImpl.enter(currentThread, tickThread);
for (E value : values) {
consumer.accept(value);
}
AcquirableImpl.leave(lock);
}
}
}
public void acquireAsync(@NotNull Consumer consumer) {
AsyncUtils.runAsync(() -> acquireSync(consumer));
}
public @NotNull Stream unwrap() {
return acquirableCollection.stream().map(Acquirable::unwrap);
}
@Override
public int size() {
return acquirableCollection.size();
}
@Override
public boolean isEmpty() {
return acquirableCollection.isEmpty();
}
@Override
public boolean contains(Object o) {
return acquirableCollection.contains(o);
}
@NotNull
@Override
public Iterator> iterator() {
return acquirableCollection.iterator();
}
@NotNull
@Override
public Object[] toArray() {
return acquirableCollection.toArray();
}
@NotNull
@Override
public T[] toArray(@NotNull T[] a) {
return acquirableCollection.toArray(a);
}
@Override
public boolean add(Acquirable eAcquirable) {
return acquirableCollection.add(eAcquirable);
}
@Override
public boolean remove(Object o) {
return acquirableCollection.remove(o);
}
@Override
public boolean containsAll(@NotNull Collection> c) {
return acquirableCollection.containsAll(c);
}
@Override
public boolean addAll(@NotNull Collection extends Acquirable> c) {
return acquirableCollection.addAll(c);
}
@Override
public boolean removeAll(@NotNull Collection> c) {
return acquirableCollection.removeAll(c);
}
@Override
public boolean retainAll(@NotNull Collection> c) {
return acquirableCollection.retainAll(c);
}
@Override
public void clear() {
this.acquirableCollection.clear();
}
/**
* Creates
*
* @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
* @return a new Thread to acquirable elements map
*/
protected static Map> retrieveOptionalThreadMap(@NotNull Collection> collection,
@NotNull Thread currentThread,
@NotNull Consumer consumer) {
// Separate a collection of acquirable elements into a map of thread->elements
// Useful to reduce the number of acquisition
Map> threadCacheMap = new HashMap<>();
for (var element : collection) {
final T value = element.unwrap();
final TickThread elementThread = element.assignedThread();
if (currentThread == elementThread) {
// The element is managed in the current thread, consumer can be immediately called
consumer.accept(value);
} else {
// The element is manager in a different thread, cache it
List threadCacheList = threadCacheMap.computeIfAbsent(elementThread, tickThread -> new ArrayList<>());
threadCacheList.add(value);
}
}
return threadCacheMap;
}
}