135 lines
		
	
	
	
		
			3.4 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			135 lines
		
	
	
	
		
			3.4 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| package net.minecraft.util.thread;
 | |
| 
 | |
| import com.google.common.collect.ImmutableList;
 | |
| import com.mojang.logging.LogUtils;
 | |
| import java.util.List;
 | |
| import java.util.concurrent.Executor;
 | |
| import java.util.concurrent.RejectedExecutionException;
 | |
| import java.util.concurrent.atomic.AtomicReference;
 | |
| import net.minecraft.Util;
 | |
| import net.minecraft.util.profiling.metrics.MetricCategory;
 | |
| import net.minecraft.util.profiling.metrics.MetricSampler;
 | |
| import net.minecraft.util.profiling.metrics.MetricsRegistry;
 | |
| import net.minecraft.util.profiling.metrics.ProfilerMeasured;
 | |
| import org.slf4j.Logger;
 | |
| 
 | |
| public abstract class AbstractConsecutiveExecutor<T extends Runnable> implements ProfilerMeasured, TaskScheduler<T>, Runnable {
 | |
| 	private static final Logger LOGGER = LogUtils.getLogger();
 | |
| 	private final AtomicReference<AbstractConsecutiveExecutor.Status> status = new AtomicReference(AbstractConsecutiveExecutor.Status.SLEEPING);
 | |
| 	private final StrictQueue<T> queue;
 | |
| 	private final Executor executor;
 | |
| 	private final String name;
 | |
| 
 | |
| 	public AbstractConsecutiveExecutor(StrictQueue<T> queue, Executor executor, String name) {
 | |
| 		this.executor = executor;
 | |
| 		this.queue = queue;
 | |
| 		this.name = name;
 | |
| 		MetricsRegistry.INSTANCE.add(this);
 | |
| 	}
 | |
| 
 | |
| 	private boolean canBeScheduled() {
 | |
| 		return !this.isClosed() && !this.queue.isEmpty();
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public void close() {
 | |
| 		this.status.set(AbstractConsecutiveExecutor.Status.CLOSED);
 | |
| 	}
 | |
| 
 | |
| 	private boolean pollTask() {
 | |
| 		if (!this.isRunning()) {
 | |
| 			return false;
 | |
| 		} else {
 | |
| 			Runnable runnable = this.queue.pop();
 | |
| 			if (runnable == null) {
 | |
| 				return false;
 | |
| 			} else {
 | |
| 				Util.runNamed(runnable, this.name);
 | |
| 				return true;
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public void run() {
 | |
| 		try {
 | |
| 			this.pollTask();
 | |
| 		} finally {
 | |
| 			this.setSleeping();
 | |
| 			this.registerForExecution();
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public void runAll() {
 | |
| 		try {
 | |
| 			while (this.pollTask()) {
 | |
| 			}
 | |
| 		} finally {
 | |
| 			this.setSleeping();
 | |
| 			this.registerForExecution();
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public void schedule(T task) {
 | |
| 		this.queue.push(task);
 | |
| 		this.registerForExecution();
 | |
| 	}
 | |
| 
 | |
| 	private void registerForExecution() {
 | |
| 		if (this.canBeScheduled() && this.setRunning()) {
 | |
| 			try {
 | |
| 				this.executor.execute(this);
 | |
| 			} catch (RejectedExecutionException var4) {
 | |
| 				try {
 | |
| 					this.executor.execute(this);
 | |
| 				} catch (RejectedExecutionException var3) {
 | |
| 					LOGGER.error("Could not schedule ConsecutiveExecutor", (Throwable)var3);
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public int size() {
 | |
| 		return this.queue.size();
 | |
| 	}
 | |
| 
 | |
| 	public boolean hasWork() {
 | |
| 		return this.isRunning() && !this.queue.isEmpty();
 | |
| 	}
 | |
| 
 | |
| 	public String toString() {
 | |
| 		return this.name + " " + this.status.get() + " " + this.queue.isEmpty();
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public String name() {
 | |
| 		return this.name;
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public List<MetricSampler> profiledMetrics() {
 | |
| 		return ImmutableList.of(MetricSampler.create(this.name + "-queue-size", MetricCategory.CONSECUTIVE_EXECUTORS, this::size));
 | |
| 	}
 | |
| 
 | |
| 	private boolean setRunning() {
 | |
| 		return this.status.compareAndSet(AbstractConsecutiveExecutor.Status.SLEEPING, AbstractConsecutiveExecutor.Status.RUNNING);
 | |
| 	}
 | |
| 
 | |
| 	private void setSleeping() {
 | |
| 		this.status.compareAndSet(AbstractConsecutiveExecutor.Status.RUNNING, AbstractConsecutiveExecutor.Status.SLEEPING);
 | |
| 	}
 | |
| 
 | |
| 	private boolean isRunning() {
 | |
| 		return this.status.get() == AbstractConsecutiveExecutor.Status.RUNNING;
 | |
| 	}
 | |
| 
 | |
| 	private boolean isClosed() {
 | |
| 		return this.status.get() == AbstractConsecutiveExecutor.Status.CLOSED;
 | |
| 	}
 | |
| 
 | |
| 	static enum Status {
 | |
| 		SLEEPING,
 | |
| 		RUNNING,
 | |
| 		CLOSED;
 | |
| 	}
 | |
| }
 |