From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Kevin Raneri Date: Tue, 9 Nov 2021 23:36:56 -0500 Subject: [PATCH] Pufferfish: Utils Original license: GPL v3 Original project: https://github.com/pufferfish-gg/Pufferfish diff --git a/src/main/java/gg/pufferfish/pufferfish/util/AsyncExecutor.java b/src/main/java/gg/pufferfish/pufferfish/util/AsyncExecutor.java new file mode 100644 index 0000000000000000000000000000000000000000..b8f01ce7f4e260f6e871dcc9cd628094b3184fb9 --- /dev/null +++ b/src/main/java/gg/pufferfish/pufferfish/util/AsyncExecutor.java @@ -0,0 +1,76 @@ +package gg.pufferfish.pufferfish.util; + +import com.google.common.collect.Queues; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.Marker; + +import java.util.Queue; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; +import java.util.logging.Level; + +public class AsyncExecutor implements Runnable { + + private final Logger LOGGER = LogManager.getLogger("Leaf"); + private final Queue jobs = Queues.newArrayDeque(); + private final Lock mutex = new ReentrantLock(); + private final Condition cond = mutex.newCondition(); + private final Thread thread; + private volatile boolean killswitch = false; + + public AsyncExecutor(String threadName) { + this.thread = new Thread(this, threadName); + } + + public void start() { + thread.start(); + } + + public void kill() { + killswitch = true; + cond.signalAll(); + } + + public void submit(Runnable runnable) { + mutex.lock(); + try { + jobs.offer(runnable); + cond.signalAll(); + } finally { + mutex.unlock(); + } + } + + @Override + public void run() { + while (!killswitch) { + try { + Runnable runnable = takeRunnable(); + if (runnable != null) { + runnable.run(); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } catch (Exception e) { + LOGGER.error("Failed to execute async job for thread {}", thread.getName(), e); + } + } + } + + private Runnable takeRunnable() throws InterruptedException { + mutex.lock(); + try { + while (jobs.isEmpty() && !killswitch) { + cond.await(); + } + + if (jobs.isEmpty()) return null; // We've set killswitch + + return jobs.remove(); + } finally { + mutex.unlock(); + } + } +} diff --git a/src/main/java/gg/pufferfish/pufferfish/util/IterableWrapper.java b/src/main/java/gg/pufferfish/pufferfish/util/IterableWrapper.java new file mode 100644 index 0000000000000000000000000000000000000000..8b4a51ae41e99d41a1095333c2036efcc9a38973 --- /dev/null +++ b/src/main/java/gg/pufferfish/pufferfish/util/IterableWrapper.java @@ -0,0 +1,20 @@ +package gg.pufferfish.pufferfish.util; + +import java.util.Iterator; + +import org.jetbrains.annotations.NotNull; + +public class IterableWrapper implements Iterable { + + private final Iterator iterator; + + public IterableWrapper(Iterator iterator) { + this.iterator = iterator; + } + + @NotNull + @Override + public Iterator iterator() { + return iterator; + } +} diff --git a/src/main/java/gg/pufferfish/pufferfish/util/Long2ObjectOpenHashMapWrapper.java b/src/main/java/gg/pufferfish/pufferfish/util/Long2ObjectOpenHashMapWrapper.java new file mode 100644 index 0000000000000000000000000000000000000000..5578acce073cea8a60619e634b3862624c8a1ae8 --- /dev/null +++ b/src/main/java/gg/pufferfish/pufferfish/util/Long2ObjectOpenHashMapWrapper.java @@ -0,0 +1,42 @@ +package gg.pufferfish.pufferfish.util; + +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; + +import java.util.Map; + +import org.jetbrains.annotations.Nullable; + +public class Long2ObjectOpenHashMapWrapper extends Long2ObjectOpenHashMap { + + private final Map backingMap; + + public Long2ObjectOpenHashMapWrapper(Map map) { + backingMap = map; + } + + @Override + public V put(Long key, V value) { + return backingMap.put(key, value); + } + + @Override + public V get(Object key) { + return backingMap.get(key); + } + + @Override + public V remove(Object key) { + return backingMap.remove(key); + } + + @Nullable + @Override + public V putIfAbsent(Long key, V value) { + return backingMap.putIfAbsent(key, value); + } + + @Override + public int size() { + return backingMap.size(); + } +}