package the8472.utils.concurrent;

import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.function.Predicate;

public class SerializedTaskExecutor {
	
	public static <T> Consumer<T> runSerialized(Consumer<T> task) {
		AtomicBoolean lock = new AtomicBoolean();
		Queue<T> q = new ConcurrentLinkedQueue<>();
		
		Predicate<T> tryRun = (T toTry) -> {
			boolean success = false;
			while(lock.compareAndSet(false, true)) {
				try {
					if(toTry != null) {
						task.accept(toTry);
						success = true;
					}
					T other;
					while((other = q.poll()) != null)
						task.accept(other);
				} finally {
					lock.set(false);
				}

				if(q.peek() == null)
					break;
			}
			return success;
		};
		
		return (T r) -> {
			
			// attempt to execute on current thread
			if(lock.get() == false && tryRun.test(r)) {
				// success
			} else {
				// execution on current thread failed, enqueue
				q.add(r);
				// try again in case other thread ceased draining the queue
				if(lock.get() == false)
					tryRun.test(null);
			}
		};
	}
	
	public static Runnable onceMore(Runnable loopBody) {
		AtomicInteger lock = new AtomicInteger();
		
		return () -> {

			// request execution of the runnable
			int current = lock.incrementAndGet();
			
			// another thread is executing
			if(current > 1)
				return;
			
			do {
				loopBody.run();
				
				current = lock.addAndGet(Math.negateExact(current));
			} while(current > 0);
		};
	}

}

@@ -980,23 +980,28 @@
 test(r))
- %7B
 %0A%09%09%09%09
+return;
 // succe
@@ -1010,18 +1010,9 @@
 %0A%09%09%09
-%7D else %7B%0A%09
+%0A
 %09%09%09/
@@ -1060,17 +1060,16 @@
 ueue%0A%09%09%09
-%09
 q.add(r)
@@ -1070,17 +1070,16 @@
 add(r);%0A
-%09
 %09%09%09// tr
@@ -1136,19 +1136,19 @@
 ueue%0A%09%09%09
-%09
 if
+ 
 (lock.ge
@@ -1165,17 +1165,16 @@
 se)%0A%09%09%09%09
-%09
 tryRun.t
@@ -1187,17 +1187,16 @@
 ll);%0A%09%09%09
-%7D
 %0A%09%09%7D;%0A%09%7D

improve control flow readability