├── .jitpack.yml ├── settings.gradle └── src └── edu └── lsu └── cct └── javalineer ├── Get.java ├── Set.java ├── GuardTask1.java ├── CondCheck1.java ├── GuardTask2.java ├── Then2.java ├── CondCheck2.java ├── GuardTask3.java ├── Then3.java ├── CondCheck3.java ├── CondArg2f.java ├── GuardTask4.java ├── OptionalGuardTask1.java ├── Guarded.java ├── CondAct.java ├── CondArg1.java ├── OptionalGuardTask2.java ├── CondArg2.java ├── OptionalGuardTask3.java ├── CondArg3.java ├── CondArgN.java ├── OptionalGuardTask4.java ├── test ├── Test.java ├── CondFut.java ├── TestRunNowVars.java ├── TestGuard.java ├── TestFib.java ├── TestBank.java ├── TestBank2.java ├── TestRunNow.java ├── TestBank3.java ├── March2.java ├── Bank.java └── March.java ├── CondTask.java ├── Here.java ├── CondLink.java ├── Val.java ├── CondTask1.java ├── Var.java ├── CondTask2.java ├── Cond.java ├── CondTask3.java ├── GuardVar.java ├── Pool.java ├── CondMgr.java ├── GuardTask.java ├── MyPool.java └── Guard.java /.jitpack.yml: -------------------------------------------------------------------------------- 1 | jdk: 2 | - openjdk11 3 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'javalineer' 2 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/Get.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer; 2 | 3 | public interface Get { 4 | T get(); 5 | } 6 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/Set.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer; 2 | 3 | public interface Set { 4 | void set(T t); 5 | } 6 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/GuardTask1.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer; 2 | 3 | public interface GuardTask1 { 4 | void run(Var v); 5 | } 6 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/CondCheck1.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer; 2 | 3 | public interface CondCheck1 { 4 | public boolean check(Var t); 5 | } 6 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/GuardTask2.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer; 2 | 3 | public interface GuardTask2 { 4 | void run(Var v1,Var v2); 5 | } 6 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/Then2.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer; 2 | 3 | public interface Then2 { 4 | public R apply(V1 v1, V2 v2) throws Exception; 5 | } 6 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/CondCheck2.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer; 2 | 3 | public interface CondCheck2 { 4 | public boolean check(Var t1,Var t2); 5 | } 6 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/GuardTask3.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer; 2 | 3 | public interface GuardTask3 { 4 | void run(Var v1,Var v2,Var v3); 5 | } 6 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/Then3.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer; 2 | 3 | public interface Then3 { 4 | public R apply(V1 v1, V2 v2,V3 v3) throws Exception; 5 | } 6 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/CondCheck3.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer; 2 | 3 | public interface CondCheck3 { 4 | public boolean check(Var t1,Var t2,Var t3); 5 | } 6 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/CondArg2f.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer; 2 | 3 | import java.util.List; 4 | 5 | public interface CondArg2f { 6 | boolean run(Var v1,Var v2); 7 | } 8 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/GuardTask4.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer; 2 | 3 | public interface GuardTask4 { 4 | void run(Var v1, Var v2, Var v3, Var v4); 5 | } 6 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/OptionalGuardTask1.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer; 2 | 3 | import java.util.Optional; 4 | 5 | public interface OptionalGuardTask1 { 6 | void run(Optional> o); 7 | } 8 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/Guarded.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer; 2 | 3 | public class Guarded { 4 | Guard g; 5 | public Guard getGuard() { return g; } 6 | void setGuard(Guard g) { this.g = g; } 7 | } 8 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/CondAct.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer; 2 | 3 | import java.util.concurrent.CompletableFuture; 4 | 5 | public interface CondAct { 6 | void act(CompletableFuture _result); 7 | } 8 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/CondArg1.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer; 2 | 3 | import java.util.concurrent.CompletableFuture; 4 | 5 | public interface CondArg1 { 6 | void run(Var v, CompletableFuture fb); 7 | } 8 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/OptionalGuardTask2.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer; 2 | 3 | import java.util.Optional; 4 | 5 | public interface OptionalGuardTask2 { 6 | void run(Optional> o1, Optional> o2); 7 | } 8 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/CondArg2.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer; 2 | 3 | import java.util.concurrent.CompletableFuture; 4 | 5 | public interface CondArg2 { 6 | void run(Var v1, Var v2, CompletableFuture fb); 7 | } 8 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/OptionalGuardTask3.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer; 2 | 3 | import java.util.Optional; 4 | 5 | public interface OptionalGuardTask3 { 6 | void run(Optional> o1, Optional> o2, Optional> o3); 7 | } -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/CondArg3.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer; 2 | 3 | import java.util.concurrent.CompletableFuture; 4 | 5 | public interface CondArg3 { 6 | void run(Var v1, Var v2, Var v3, CompletableFuture fb); 7 | } 8 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/CondArgN.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer; 2 | 3 | import java.util.List; 4 | import java.util.concurrent.CompletableFuture; 5 | 6 | public interface CondArgN { 7 | void run(List> v, CompletableFuture fb); 8 | } 9 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/OptionalGuardTask4.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer; 2 | 3 | import java.util.Optional; 4 | 5 | public interface OptionalGuardTask4 { 6 | void run(Optional> o1, Optional> o2, Optional> o3, Optional> o4); 7 | } -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/test/Test.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer.test; 2 | 3 | public class Test { 4 | public static void requireAssert() { 5 | try { 6 | assert false; 7 | throw new Error("Please enable assertions."); 8 | } catch(AssertionError ae) { 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/CondTask.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer; 2 | 3 | import java.util.concurrent.CompletableFuture; 4 | 5 | public abstract class CondTask implements Runnable { 6 | volatile boolean done = false; 7 | final CompletableFuture fut = new CompletableFuture<>(); 8 | 9 | public abstract void run(); 10 | 11 | public final boolean isDone() { return done; } 12 | } 13 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/Here.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer; 2 | 3 | public class Here { 4 | public static void println(Object out) { 5 | Throwable t = new Throwable(); 6 | StackTraceElement[] elems = t.getStackTrace(); 7 | System.out.println(elems[1]+": "+out); 8 | } 9 | public static void print(Object out) { 10 | Throwable t = new Throwable(); 11 | StackTraceElement[] elems = t.getStackTrace(); 12 | System.out.print(elems[1]+": "+out); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/CondLink.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer; 2 | 3 | import java.util.concurrent.atomic.AtomicReference; 4 | import java.util.concurrent.atomic.AtomicBoolean; 5 | import java.util.concurrent.atomic.AtomicInteger; 6 | import java.util.function.Consumer; 7 | 8 | public class CondLink { 9 | volatile AtomicReference next = new AtomicReference<>(null); 10 | final Cond cond; 11 | final Error err = new Error(); 12 | public CondLink(Cond c) { cond = c; } 13 | public String toString() { 14 | return cond.toString()+"|"+next; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/Val.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer; 2 | 3 | public class Val { 4 | T data; 5 | Throwable ex; 6 | 7 | Val(T t,Throwable ex) { data = t; this.ex = ex; } 8 | 9 | public T get() { 10 | if(ex != null) 11 | throw new RuntimeException(ex); 12 | return data; 13 | } 14 | public T getNoEx() { 15 | return data; 16 | } 17 | public Throwable getEx() { 18 | return ex; 19 | } 20 | public String toString() { 21 | if(ex != null) 22 | return ex.toString(); 23 | if(data != null) 24 | return data.toString(); 25 | return "null"; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/CondTask1.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer; 2 | 3 | public class CondTask1 extends CondTask { 4 | Var t; 5 | public void set1(Var t) { this.t = t; } 6 | 7 | public final CondCheck1 check; 8 | public CondTask1(CondCheck1 check) { 9 | this.check = check; 10 | } 11 | 12 | public final void run() { 13 | if (!done) { 14 | try { 15 | done = check.check(t); 16 | if (done) { 17 | fut.complete(null); 18 | } 19 | } catch (Exception e) { 20 | done = true; 21 | fut.completeExceptionally(e); 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/test/CondFut.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer.test; 2 | 3 | import edu.lsu.cct.javalineer.Guard; 4 | import edu.lsu.cct.javalineer.GuardVar; 5 | import edu.lsu.cct.javalineer.Pool; 6 | 7 | public class CondFut { 8 | public static void main(String[] args) { 9 | GuardVar counter = new GuardVar<>(0); // 0 10 | 11 | var f = Guard.runCondition(counter, (v) -> { 12 | v.set(v.get() + 1); 13 | return v.get() == 2; 14 | }); // 1 15 | 16 | counter.signal(); // 2 17 | 18 | f.thenRun(() -> { 19 | counter.runGuarded((v) -> { 20 | System.out.println("2 == " + v.get()); 21 | assert v.get() == 2; 22 | }); 23 | }); 24 | 25 | Pool.await(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/Var.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer; 2 | 3 | public class Var implements Get, Set { 4 | final Guard g; 5 | T data; 6 | 7 | Var(T t,Guard g) { data = t; this.g = g; } 8 | 9 | public void set(T t) { 10 | assert Guard.has(g) : "The current thread does not have access to this Guard."; 11 | data = t; 12 | } 13 | 14 | public T get() { 15 | assert Guard.has(g) : "The current thread does not have access to this Guard."; 16 | return data; 17 | } 18 | 19 | public void signal() { 20 | g.signal(); 21 | } 22 | 23 | public void signalAll() { 24 | g.signalAll(); 25 | } 26 | 27 | @SuppressWarnings("unchecked") 28 | public GuardVar guardVar() { 29 | return (GuardVar)g; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/CondTask2.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer; 2 | 3 | public class CondTask2 extends CondTask { 4 | Var t1; 5 | Var t2; 6 | public void set1(Var t1) { this.t1 = t1; } 7 | public void set2(Var t2) { this.t2 = t2; } 8 | 9 | public final CondCheck2 check; 10 | public CondTask2(CondCheck2 check) { 11 | this.check = check; 12 | } 13 | 14 | public final void run() { 15 | if (!done) { 16 | try { 17 | done = check.check(t1, t2); 18 | if (done) { 19 | fut.complete(null); 20 | } 21 | } catch (Exception e) { 22 | done = true; 23 | fut.completeExceptionally(e); 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/Cond.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer; 2 | 3 | import java.util.concurrent.atomic.AtomicReference; 4 | import java.util.concurrent.atomic.AtomicBoolean; 5 | import java.util.concurrent.atomic.AtomicInteger; 6 | import java.util.function.Consumer; 7 | import java.util.TreeSet; 8 | 9 | public class Cond { 10 | // 0 -> ready 11 | // 1 -> complete 12 | // 2+ -> busy 13 | static AtomicInteger idSeq = new AtomicInteger(0); 14 | final int id = idSeq.incrementAndGet(); 15 | final Throwable t = new Throwable(); 16 | final static int READY = 0, FINISHED = 1, BUSY = 0; 17 | final AtomicInteger state = new AtomicInteger(0); 18 | volatile CondTask task; 19 | TreeSet gset; 20 | public String toString() { 21 | //return task.toString()+":id="+state.get(); 22 | return "Cond:"+id; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/CondTask3.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer; 2 | 3 | public class CondTask3 extends CondTask { 4 | Var t1; 5 | Var t2; 6 | Var t3; 7 | public void set1(Var t1) { this.t1 = t1; } 8 | public void set2(Var t2) { this.t2 = t2; } 9 | public void set3(Var t3) { this.t3 = t3; } 10 | 11 | public final CondCheck3 check; 12 | public CondTask3(CondCheck3 check) { 13 | this.check = check; 14 | } 15 | 16 | public final void run() { 17 | if (!done) { 18 | try { 19 | done = check.check(t1, t2, t3); 20 | if (done) { 21 | fut.complete(null); 22 | } 23 | } catch (Exception e) { 24 | done = true; 25 | fut.completeExceptionally(e); 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/test/TestRunNowVars.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer.test; 2 | 3 | import edu.lsu.cct.javalineer.Guard; 4 | import edu.lsu.cct.javalineer.GuardVar; 5 | import edu.lsu.cct.javalineer.Pool; 6 | 7 | public class TestRunNowVars { 8 | public static void main(String[] args) { 9 | var g1 = new GuardVar<>("g1's data"); 10 | var g2 = new GuardVar<>("g2's data"); 11 | 12 | Guard.runGuarded(g1, v -> { 13 | System.out.println("Doing something slow with g1 ..."); 14 | try { 15 | Thread.sleep(5000); 16 | } catch (InterruptedException ignored) { } 17 | System.out.println("Done with g1"); 18 | }); 19 | 20 | Guard.now(g1, g2, (o1, o2) -> { 21 | System.out.println(o1); 22 | System.out.println(o2); 23 | }); 24 | 25 | Guard.runGuarded(g1, g2, (v1, v2) -> { 26 | System.out.println(v1); 27 | System.out.println(v2); 28 | }); 29 | 30 | Pool.await(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/GuardVar.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer; 2 | 3 | import java.util.concurrent.Callable; 4 | import java.util.function.Consumer; 5 | import java.util.function.Function; 6 | import java.util.TreeSet; 7 | import java.util.List; 8 | import java.util.ArrayList; 9 | 10 | public class GuardVar extends Guard { 11 | final Var var; 12 | 13 | public GuardVar(T t) { 14 | var = new Var<>(t,this); 15 | if(t instanceof Guarded) { 16 | Guarded g = (Guarded)t; 17 | g.setGuard(this); 18 | } 19 | } 20 | 21 | public void runGuarded(Consumer> c) { 22 | runGuarded(()->{ c.accept(var); }); 23 | } 24 | 25 | public static void runGuarded(List> guards,final Consumer>> vars) { 26 | TreeSet ts = new TreeSet<>(); 27 | List> result = new ArrayList<>(); 28 | for(GuardVar gv : guards) { 29 | ts.add(gv); 30 | result.add(gv.var); 31 | } 32 | Runnable r = () -> { vars.accept(result); }; 33 | Guard.runGuarded(ts,r); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/test/TestGuard.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer.test; 2 | 3 | import edu.lsu.cct.javalineer.*; 4 | import java.util.*; 5 | 6 | public class TestGuard { 7 | static int c1 = 0, c2 = 0; 8 | final static int N_INCR = 100; 9 | final static int N_TASK = 1000; 10 | 11 | static void incrC1() { 12 | for(int i=0;i ts = new TreeSet<>(); 24 | ts.add(g1); 25 | ts.add(g2); 26 | 27 | for(int i=0;i{ incrC1(); }); 29 | Guard.runGuarded(g2,()->{ incrC2(); }); 30 | Guard.runGuarded(ts,()->{ incrC1(); incrC2(); }); 31 | } 32 | Pool.await(); 33 | System.out.printf("c1=%d, c2=%d%n",c1,c2); 34 | assert 2*N_TASK*N_INCR == c1; 35 | assert 2*N_TASK*N_INCR == c2; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/test/TestFib.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer.test; 2 | 3 | import edu.lsu.cct.javalineer.*; 4 | 5 | import java.util.concurrent.CompletableFuture; 6 | 7 | public class TestFib { 8 | static int fibc(int n) { 9 | if(n < 2) return n; 10 | return fibc(n-1) + fibc(n-2); 11 | } 12 | 13 | static int fib_sync(int n) { 14 | if(n < 2) 15 | return n; 16 | else 17 | return fib_sync(n-1)+fib_sync(n-2); 18 | } 19 | 20 | static CompletableFuture fib(int n) { 21 | if (n < 2) 22 | return CompletableFuture.completedFuture(n); 23 | if (n < 20) 24 | return CompletableFuture.completedFuture(fib_sync(n)); 25 | 26 | CompletableFuture f1 = Pool.supply(() -> fib(n - 1)); 27 | CompletableFuture f2 = fib(n - 2); 28 | 29 | return f1.thenCombine(f2, Integer::sum); 30 | } 31 | 32 | public static void main(String[] args) { 33 | Test.requireAssert(); 34 | 35 | for(int i = 5; i < 40; i++) { 36 | final int f = i; 37 | fib(f).thenAccept(n -> { 38 | System.out.printf("fib(%d)=%d%n", f, n); 39 | assert n == fibc(f); 40 | }); 41 | } 42 | 43 | Pool.await(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/test/TestBank.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer.test; 2 | 3 | import edu.lsu.cct.javalineer.*; 4 | 5 | public class TestBank { 6 | 7 | static class Bank { 8 | int balance = 0; 9 | 10 | boolean withdraw(int a) { 11 | assert a > 0; 12 | if(a > balance) 13 | return false; 14 | balance -= a; 15 | return true; 16 | } 17 | 18 | void deposit(int a) { 19 | assert a > 0; 20 | balance += a; 21 | } 22 | } 23 | 24 | static int failures = 0; 25 | 26 | public static void main(String[] args) { 27 | Test.requireAssert(); 28 | 29 | GuardVar a = new GuardVar<>(new Bank()); 30 | 31 | for(int i=0;i<1000;i++) { 32 | Pool.run(()->{ 33 | a.runGuarded((bank)->{ 34 | if(!bank.get().withdraw(1)) 35 | failures++; 36 | }); 37 | }); 38 | Pool.run(()->{ 39 | a.runGuarded((bank)->{ 40 | bank.get().deposit(1); 41 | bank.signal(); 42 | }); 43 | }); 44 | } 45 | 46 | Pool.await(); 47 | int[] out = new int[1]; 48 | 49 | a.runGuarded((bank)->{ 50 | out[0] = bank.get().balance; 51 | assert out[0] == failures; 52 | }); 53 | 54 | Pool.await(); 55 | 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/Pool.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package edu.lsu.cct.javalineer; 7 | 8 | import java.util.concurrent.CompletableFuture; 9 | import java.util.concurrent.Executor; 10 | import java.util.concurrent.ForkJoinPool; 11 | import java.util.concurrent.TimeUnit; 12 | import java.util.function.Supplier; 13 | 14 | /** 15 | * 16 | * @author sbrandt 17 | */ 18 | public class Pool { 19 | private static final ForkJoinPool POOL = new ForkJoinPool( 20 | Integer.parseInt(System.getProperty("POOL_SIZE", "4")) 21 | ); 22 | 23 | static { 24 | System.out.println("Pool size: " + POOL.getParallelism()); 25 | } 26 | 27 | public static void await() { 28 | //noinspection StatementWithEmptyBody 29 | while (!await(5, TimeUnit.MINUTES)); // todo Probably should do something different 30 | } 31 | 32 | public static boolean await(long timeout, TimeUnit unit) { 33 | return POOL.awaitQuiescence(timeout, unit); 34 | } 35 | 36 | public static void run(Runnable r) { 37 | POOL.execute(r); 38 | } 39 | 40 | public static Executor getExecutor() { 41 | return POOL; 42 | } 43 | 44 | public static CompletableFuture supply(Supplier> supplier) { 45 | return CompletableFuture.completedFuture(null) 46 | .thenComposeAsync(x -> supplier.get(), POOL); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/test/TestBank2.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer.test; 2 | 3 | import edu.lsu.cct.javalineer.*; 4 | 5 | public class TestBank2 { 6 | 7 | static class Bank extends Guarded { 8 | int balance = 0; 9 | 10 | boolean withdraw(int a) { 11 | assert a > 0; 12 | if(a > balance) 13 | return false; 14 | balance -= a; 15 | return true; 16 | } 17 | 18 | void deposit(int a) { 19 | assert a > 0; 20 | balance += a; 21 | } 22 | } 23 | 24 | public static void main(String[] args) { 25 | Test.requireAssert(); 26 | 27 | GuardVar a = new GuardVar<>(new Bank()); 28 | 29 | for(int i=0;i<1000;i++) { 30 | Pool.run(()->{ 31 | Guard.runCondition(a,new CondCheck1<>() { 32 | public boolean check(Var bank) { 33 | return bank.get().withdraw(1); 34 | } 35 | }); 36 | }); 37 | Pool.run(()->{ 38 | Guard.runGuarded(a,new GuardTask1() { 39 | public void run(Var bank) { 40 | bank.get().deposit(1); 41 | bank.get().getGuard().signal(); 42 | } 43 | }); 44 | }); 45 | } 46 | 47 | Pool.await(); 48 | int[] out = new int[1]; 49 | 50 | a.runGuarded((bank)->{ 51 | out[0] = bank.get().balance; 52 | assert out[0] == 0; 53 | }); 54 | 55 | Pool.await(); 56 | 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/test/TestRunNow.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer.test; 2 | 3 | import edu.lsu.cct.javalineer.Guard; 4 | import edu.lsu.cct.javalineer.Pool; 5 | 6 | import java.util.TreeSet; 7 | 8 | public class TestRunNow { 9 | public static void main(String[] args) throws InterruptedException { 10 | Guard g1 = new Guard(); 11 | Guard g2 = new Guard(); 12 | 13 | Guard.nowOrNever(g1, () -> { 14 | System.out.println("with g1 .. nowOrNever first"); 15 | }); 16 | 17 | Guard.runGuarded(g1, () -> { 18 | System.out.println("with g1 .. normal (long task)"); 19 | try { 20 | for(int i = 0; i < 10; i++) { 21 | Thread.sleep(1000); 22 | if (!Guard.has(g1)) { 23 | System.out.println("bad"); 24 | } 25 | } 26 | } catch (InterruptedException e) { 27 | e.printStackTrace(); 28 | } 29 | System.out.println("long task ended"); 30 | }); 31 | 32 | Guard.nowOrNever(g2, () -> { 33 | System.out.println("with g2 .. nowOrNever"); 34 | }); 35 | 36 | Guard.nowOrElse(g1, () -> { 37 | System.out.println("error"); 38 | }, () -> { 39 | assert !Guard.has(g1); 40 | System.out.println("with g1 .. norOrElse, ran fallback"); 41 | }); 42 | 43 | Guard.runGuarded(g1, () -> { 44 | System.out.println("with g1 .. normal"); 45 | }); 46 | 47 | Guard.runGuarded(g1, () -> { 48 | System.out.println("with g1 .. normal"); 49 | }); 50 | 51 | Guard.nowOrNever(g2, () -> { 52 | System.out.println("with g2 .. nowOrNever"); 53 | }); 54 | 55 | Pool.await(); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/test/TestBank3.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer.test; 2 | 3 | import edu.lsu.cct.javalineer.*; 4 | import java.util.concurrent.atomic.AtomicInteger; 5 | 6 | public class TestBank3 { 7 | static AtomicInteger wc = new AtomicInteger(0), tc = new AtomicInteger(0), dc = new AtomicInteger(0); 8 | 9 | static class Bank extends Guarded { 10 | int balance = 0; 11 | 12 | boolean withdraw(int a) { 13 | assert a > 0; 14 | if(a > balance) 15 | return false; 16 | balance -= a; 17 | return true; 18 | } 19 | 20 | void deposit(int a) { 21 | assert a > 0; 22 | balance += a; 23 | } 24 | } 25 | 26 | public static void main(String[] args) { 27 | Test.requireAssert(); 28 | 29 | GuardVar a = new GuardVar<>(new Bank()); 30 | GuardVar b = new GuardVar<>(new Bank()); 31 | 32 | for(int i=0;i<1000;i++) { 33 | Pool.run(()->{ 34 | Guard.runCondition(a,(Var bank)->{ 35 | boolean b2 = bank.get().withdraw(1); 36 | if(b2) wc.getAndIncrement(); 37 | return b2; 38 | }); 39 | }); 40 | Pool.run(()->{ 41 | Guard.runCondition(a,b,(Var banka,Var bankb)->{ 42 | if(bankb.get().withdraw(1)) { 43 | banka.get().deposit(1); 44 | banka.signal(); 45 | tc.getAndIncrement(); 46 | return true; 47 | } else { 48 | return false; 49 | } 50 | }); 51 | }); 52 | Pool.run(()->{ 53 | Guard.runGuarded(b,(Var bank)->{ 54 | bank.get().deposit(1); 55 | bank.signal(); 56 | dc.getAndIncrement(); 57 | }); 58 | }); 59 | } 60 | 61 | Pool.await(); 62 | int[] out = new int[1]; 63 | System.out.println("wc="+wc+", tc="+tc+", dc="+dc); 64 | 65 | a.runGuarded((bank)->{ 66 | out[0] = bank.get().balance; 67 | assert out[0] == 0 : out[0]; 68 | }); 69 | 70 | Pool.await(); 71 | 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/CondMgr.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer; 2 | 3 | import java.util.concurrent.atomic.AtomicReference; 4 | import java.util.concurrent.atomic.AtomicBoolean; 5 | import java.util.concurrent.atomic.AtomicInteger; 6 | import java.util.function.Consumer; 7 | import java.util.TreeSet; 8 | 9 | 10 | public class CondMgr { 11 | AtomicReference head = new AtomicReference<>(null); 12 | 13 | /** 14 | * Atomically append to the front of the list. 15 | */ 16 | public void add(CondLink cl) { 17 | while(true) { 18 | cl.next.set(head.get()); 19 | if(head.compareAndSet(cl.next.get(), cl)) 20 | break; 21 | } 22 | } 23 | 24 | /** 25 | * Get a reference to the next Condition Link in 26 | * the chain. If the condition has already succeeded, 27 | * i.e. it is done, snip it out. 28 | */ 29 | private CondLink getRef(AtomicReference ref) { 30 | CondLink r = null; 31 | while(true) { 32 | r = ref.get(); 33 | if(r == null) 34 | return null; 35 | if(r.cond.task.done) { 36 | // snip out completed task 37 | CondLink r2 = r.next.get(); 38 | ref.compareAndSet(r, r2); 39 | } else 40 | break; 41 | } 42 | return r; 43 | } 44 | 45 | /** 46 | * Attempt to run each task in the condition list 47 | * until one of them succeeds, or we reach the 48 | * end of the list. 49 | */ 50 | public void signal() { 51 | CondLink cl = getRef(head); 52 | signal(cl); 53 | } 54 | 55 | private void signal(CondLink cl) { 56 | if(cl != null) { 57 | if(cl.cond == null) throw cl.err; 58 | assert cl.cond.gset != null; 59 | final CondLink cf = cl; 60 | final CondTask task = cl.cond.task; 61 | Guard.runGuarded(cl.cond.gset,()->{ 62 | if(task.done) { 63 | signal(getRef(cf.next)); 64 | return; 65 | } 66 | task.run(); 67 | if(!task.done) 68 | signal(getRef(cf.next)); 69 | }); 70 | } 71 | } 72 | 73 | /** 74 | * Run all tasks in the condition list. 75 | */ 76 | public void signalAll() { 77 | CondLink cl = getRef(head); 78 | while(cl != null) { 79 | Guard.runGuarded(cl.cond.gset, cl.cond.task); 80 | cl = getRef(cl.next); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/test/March2.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer.test; 2 | 3 | import java.util.*; 4 | import edu.lsu.cct.javalineer.*; 5 | import java.util.concurrent.atomic.AtomicInteger; 6 | 7 | public class March2 implements Runnable { 8 | final static int N_SEGS = 100; 9 | static class Segment { 10 | GuardVar left, right; 11 | int step; 12 | final int id; 13 | Segment() { this.id = -1; step = N_SEGS; } 14 | Segment(int id) { this.id = id; } 15 | public String toString() { 16 | return "Seg("+id+","+step+")"; 17 | } 18 | } 19 | static class Stepper implements CondCheck3 { 20 | public boolean check(Var l,Var ss,Var r) { 21 | final int lstep = l.get().step; 22 | final int rstep = r.get().step; 23 | final int step = ss.get().step; 24 | //new Throwable("runstep").printStackTrace(); 25 | if(lstep >= step && rstep >= step) { 26 | /* 27 | if(ss.get().id == 0 || ss.get().id == N_SEGS-1) { 28 | ss.get().step = 10; 29 | return true; 30 | } 31 | */ 32 | ss.get().step++; 33 | Stepper stepper = new Stepper(); 34 | Guard.runCondition(l.guardVar(), ss.guardVar(), r.guardVar(), stepper); 35 | boolean show = ss.get().id == 0;// || ss.get().id == N_SEGS/2; 36 | if(show) 37 | Here.print("id: "+ss.get().id+", step: s="+ss.get().step+"/r="+rstep+"/l="+lstep); 38 | if(ss.get().id > 0) { 39 | l.signal(); 40 | if(ss.get().id==0) 41 | System.out.print(" left:"+l.get().id); 42 | } 43 | if(ss.get().id < N_SEGS-1) { 44 | r.signal(); 45 | if(show) 46 | System.out.print(" right:"+r.get().id); 47 | } 48 | if(show) 49 | System.out.println(); 50 | return true; 51 | } else { 52 | //Here.println(" -> id: "+ss.get().id+", step: s="+ss.get().step+"/r="+rstep+"/l="+lstep); 53 | } 54 | return false; 55 | } 56 | } 57 | 58 | public void run() { 59 | List> line = new ArrayList<>(); 60 | for(int i=0;i(new Segment(i))); 62 | } 63 | final GuardVar send = new GuardVar<>(new Segment()); 64 | final AtomicInteger ai = new AtomicInteger(0); 65 | for(int i=0;i{ 68 | int i0 = ix - 1; 69 | int iN = ix + 1; 70 | if(i0 < 0) 71 | s.get().left = send; 72 | else 73 | s.get().left = line.get(i0); 74 | if(iN >= line.size()) 75 | s.get().right = send; 76 | else 77 | s.get().right = line.get(iN); 78 | int nv = ai.incrementAndGet(); 79 | var rstep = s.get().right; 80 | var lstep = s.get().left; 81 | Here.println("nv="+nv); 82 | if(nv == N_SEGS) { 83 | for(int j=0;j{ 85 | Guard.runCondition(ss.get().left,ss.guardVar(),ss.get().right,new Stepper()); 86 | }); 87 | } 88 | } 89 | }); 90 | } 91 | } 92 | 93 | public static void main(String[] args) { 94 | Test.requireAssert(); 95 | Pool.run(new March2()); 96 | Pool.await(); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/test/Bank.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer.test; 2 | 3 | import edu.lsu.cct.javalineer.*; 4 | import java.util.concurrent.atomic.AtomicInteger; 5 | import java.util.concurrent.CompletableFuture; 6 | 7 | import java.util.List; 8 | import edu.lsu.cct.javalineer.Guard; 9 | import edu.lsu.cct.javalineer.GuardVar; 10 | import java.util.concurrent.*; 11 | //import edu.lsu.cct.javalineer.CompletableFuture; 12 | 13 | import java.io.PrintStream; 14 | 15 | 16 | public class Bank { 17 | public static class Printy {} 18 | public final String name; 19 | public Bank(String name) { 20 | this.name = name; 21 | } 22 | 23 | private final static GuardVar printer = new GuardVar<>(new Printy()); 24 | private static void print(String s) { 25 | Guard.runGuarded(printer, (pr)->{ 26 | System.out.println(s); 27 | }); 28 | } 29 | private final GuardVar balance = new GuardVar<>(0.0); 30 | 31 | public CompletableFuture deposit(int amount) { 32 | assert amount > 0; 33 | CompletableFuture done = new CompletableFuture<>(); 34 | Guard.runGuarded(balance,(b)->{ 35 | b.set(b.get() + amount); 36 | print(String.format("deposit: %s %.2f",this.name,b.get())); 37 | balance.signal(); 38 | done.complete(null); 39 | }); 40 | return done; 41 | } 42 | 43 | /** 44 | * If the amount is insufficient, it 45 | * waits until it is. 46 | */ 47 | public void withdraw(int amount) { 48 | assert amount > 0; 49 | Guard.runCondition(balance,(b)->{ 50 | if(amount > b.get()) 51 | return false; 52 | b.set(b.get() - amount); 53 | print(String.format("withdraw: %s %.2f",name,b.get())); 54 | return true; 55 | }); 56 | } 57 | 58 | public static CompletableFuture withdrawFromLarger(Bank b1, Bank b2, double amount) { 59 | CompletableFuture done = new CompletableFuture<>(); 60 | Guard.runCondition(b1.balance,b2.balance,(bb1, bb2)->{ 61 | if (bb1.get() >= bb2.get() && amount < bb1.get()) { 62 | bb1.set(bb1.get() - amount); 63 | print("Decr b1"); 64 | return true; 65 | } else if (bb2.get() >= bb1.get() && amount < bb2.get()) { 66 | bb2.set(bb2.get() - amount); 67 | print(String.format("Decr b2 = %.2f", bb2.get())); 68 | done.complete(null); 69 | return true; 70 | } else { 71 | print("wait..."); 72 | return false; 73 | } 74 | }); 75 | return done; 76 | } 77 | 78 | public CompletableFuture getBalance() { 79 | CompletableFuture done = new CompletableFuture<>(); 80 | Guard.runGuarded(this.balance,(b)->{ 81 | done.complete(b.get()); 82 | }); 83 | return done; 84 | } 85 | 86 | public static void main(String[] args) { 87 | //Tripwire.incr(); // atomic static must be zero at the end 88 | Bank b1 = new Bank("Joe"); 89 | Bank b2 = new Bank("Fred"); 90 | b1.deposit(1000); 91 | b2.deposit(1000); 92 | b1.withdraw(1100); 93 | b1.deposit(200); 94 | var v1 = withdrawFromLarger(b1,b2,10000); 95 | b2.deposit(20000); 96 | v1.thenAccept((v1_)->{ 97 | b1.getBalance().thenAccept((a)->{ 98 | b2.getBalance().thenAccept((b)->{ 99 | print(String.format("b1 = %.2f, b2 = %.2f", a, b)); 100 | //Tripwire.decr(); 101 | print("Done"); 102 | }); 103 | }); 104 | }); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/GuardTask.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package edu.lsu.cct.javalineer; 7 | 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | import java.util.Set; 11 | import java.util.TreeSet; 12 | import java.util.concurrent.atomic.AtomicInteger; 13 | import java.util.concurrent.atomic.AtomicReference; 14 | 15 | /** 16 | * 17 | * @author sbrandt 18 | */ 19 | public class GuardTask { 20 | static AtomicInteger idSeq = new AtomicInteger(0); 21 | final int id = idSeq.getAndIncrement(); 22 | 23 | public String toString() { 24 | return "GuardTask("+id+")"; 25 | } 26 | 27 | public final static GuardTask DONE = new GuardTask(new TreeSet<>(),()->{}); 28 | final List> next = new ArrayList<>(); 29 | 30 | private final List gset = new ArrayList<>(); 31 | private final Runnable r; 32 | private volatile int index = 0; 33 | 34 | public final static ThreadLocal> GUARDS_HELD = new ThreadLocal<>(); 35 | 36 | static void run(Runnable r,List gset) { 37 | try { 38 | TreeSet ts = new TreeSet<>(); 39 | ts.addAll(gset); 40 | assert GUARDS_HELD.get() == null; 41 | GUARDS_HELD.set(ts); 42 | r.run(); 43 | } catch(Exception e) { 44 | e.printStackTrace(); 45 | System.exit(1); 46 | } catch(AssertionError e) { 47 | e.printStackTrace(); 48 | System.exit(2); 49 | } finally { 50 | GUARDS_HELD.set(null); 51 | } 52 | } 53 | 54 | GuardTask(TreeSet gset, Runnable r) { 55 | this.gset.addAll(gset); 56 | for(Guard g : gset) { 57 | next.add(new AtomicReference<>()); 58 | } 59 | this.r = r; 60 | } 61 | 62 | public void run() { 63 | if(gset.size()==0) { 64 | run(r,gset); 65 | return; 66 | } 67 | Guard g = gset.get(index); 68 | GuardTask prev = g.task.getAndSet(this); 69 | if(prev == null) { 70 | runTask(g); 71 | } else { 72 | assert prev.next.size() == prev.gset.size(); 73 | var nextt = prev.next.get(prev.index); 74 | assert nextt != null; 75 | if(!nextt.compareAndSet(null,this)) 76 | runTask(g); 77 | assert nextt.get() != null; 78 | } 79 | } 80 | 81 | public void runImmediately() { 82 | if(gset.size() == 0) { 83 | run(r, gset); 84 | return; 85 | } 86 | Guard g = gset.get(index); 87 | GuardTask prev = g.task.get(); 88 | if(prev == null) { 89 | if (g.task.compareAndSet(null, this)) { 90 | runTask(g); 91 | } else { 92 | runTask(null); 93 | } 94 | } else { 95 | assert prev.next.size() == prev.gset.size(); 96 | var nextt = prev.next.get(prev.index); 97 | assert nextt != null; 98 | if (nextt.get() == null) { 99 | runTask(null); 100 | } else if (g.task.compareAndSet(prev, this)) { 101 | runTask(g); 102 | } else { 103 | runTask(null); 104 | } 105 | } 106 | } 107 | 108 | private void free() { 109 | Guard g = gset.get(index); 110 | if (!next.get(index).compareAndSet(null, DONE)) { 111 | GuardTask prev = next.get(index).get(); 112 | assert prev != DONE; 113 | prev.runTask(g); 114 | } 115 | assert next.get(index).get() != null; 116 | if (index > 0) { 117 | index--; 118 | free(); 119 | } 120 | } 121 | 122 | private void runTask(Guard g) { 123 | if(index + 1 == gset.size()) { 124 | // Don't need to force async 125 | Pool.run(()->{ 126 | if (g == null) { 127 | run(r, List.of()); 128 | } else { 129 | run(r, gset); 130 | } 131 | free(); 132 | }); 133 | } else { 134 | index++; 135 | assert index < gset.size(); 136 | run(); 137 | } 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/MyPool.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer; 2 | 3 | import java.util.LinkedList; 4 | import java.util.Random; 5 | import java.util.concurrent.CompletableFuture; 6 | import java.util.concurrent.Executor; 7 | import java.util.function.Supplier; 8 | 9 | public class MyPool implements Executor { 10 | volatile int busy = 0; 11 | 12 | synchronized void incrBusy() { 13 | busy++; 14 | } 15 | 16 | synchronized void decrBusy() { 17 | busy--; 18 | assert busy >= 0; 19 | if (busy == 0) 20 | notifyAll(); 21 | } 22 | 23 | synchronized void awaitQuiet() { 24 | while (busy > 0) { 25 | try { 26 | wait(); 27 | } catch (InterruptedException ioe) { 28 | } 29 | } 30 | for(Worker w : workers) { 31 | assert w.ll.size()==0; 32 | } 33 | } 34 | 35 | final static ThreadLocal me = new ThreadLocal<>(); 36 | 37 | class Worker extends Thread { 38 | final int id; 39 | 40 | Worker(final int id) { 41 | this.id = id; 42 | incrBusy(); 43 | ll.add(()->{ me.set(id); }); 44 | } 45 | 46 | LinkedList ll = new LinkedList<>(); 47 | 48 | synchronized void addTask(Runnable t) { 49 | ll.addLast(t); 50 | // This worker just became busy 51 | if(ll.size() == 1) { 52 | incrBusy(); 53 | // this worker now has tasks... 54 | notifyAll(); 55 | } 56 | } 57 | 58 | synchronized Runnable rmTaskWait() { 59 | while (ll.size() == 0) { 60 | try { 61 | wait(); 62 | } catch (InterruptedException ioe) { 63 | } 64 | } 65 | return rmTask(); 66 | } 67 | synchronized Runnable rmTask() { 68 | if(ll.size() == 0) 69 | return null; 70 | Runnable gt = ll.removeFirst(); 71 | if(ll.size() == 0) { 72 | return ()->{ 73 | try { 74 | gt.run(); 75 | } finally { 76 | decrBusy(); 77 | } 78 | }; 79 | } else { 80 | return gt; 81 | } 82 | } 83 | 84 | public void run() { 85 | try { 86 | while (true) { 87 | Runnable gt = rmTaskWait(); 88 | gt.run(); 89 | } 90 | } catch (Throwable ex) { 91 | ex.printStackTrace(); 92 | System.exit(1); 93 | } 94 | } 95 | 96 | public boolean runOne() { 97 | Runnable run = rmTask(); 98 | if(run != null) { 99 | run.run(); 100 | return true; 101 | } else { 102 | return false; 103 | } 104 | } 105 | } 106 | 107 | final Random RAND = new Random(); 108 | 109 | /** 110 | * Give task to a random worker. 111 | */ 112 | void add(Runnable gt) { 113 | int n = RAND.nextInt(workers.length); 114 | workers[n].addTask(gt); 115 | } 116 | 117 | final int size; 118 | Worker[] workers; 119 | public MyPool(int size) { 120 | this.size = size; 121 | workers = new Worker[size]; 122 | for (int i = 0; i < size; i++) { 123 | Worker w = this.new Worker(i); 124 | workers[i] = w; 125 | w.setDaemon(true); 126 | w.start(); 127 | } 128 | } 129 | 130 | public boolean runOne() { 131 | assert size == workers.length; 132 | 133 | Integer meId = me.get(); 134 | // We might not be on a worker thread... 135 | if(meId == null) 136 | meId = RAND.nextInt(workers.length); 137 | 138 | for(int i=0;i CompletableFuture supply(Supplier> supplier) { 152 | return CompletableFuture.completedFuture(null) 153 | .thenComposeAsync(x -> supplier.get(), this); 154 | } 155 | 156 | public String toString() { 157 | return "MyPool("+size+")"; 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/test/March.java: -------------------------------------------------------------------------------- 1 | package edu.lsu.cct.javalineer.test; 2 | 3 | import edu.lsu.cct.javalineer.*; 4 | import java.util.*; 5 | 6 | class ProdCon { 7 | 8 | static int idSeq = 0; 9 | final int id = idSeq++; 10 | 11 | private volatile boolean readyToProduce = false; 12 | private volatile boolean readyToConsume = true; 13 | private volatile boolean alwaysReady = false; 14 | private volatile int val = 0; 15 | 16 | public ProdCon(boolean a) { 17 | alwaysReady = a; 18 | } 19 | 20 | boolean isReadyToProduce(int n) { 21 | if(alwaysReady) 22 | return true; 23 | if (val != n) { 24 | //System.out.printf("not ready to produce: %d != %d: %d%n",val,n,id); 25 | return false; 26 | } 27 | return alwaysReady || readyToProduce; 28 | } 29 | 30 | boolean isReadyToConsume(int n) { 31 | if(alwaysReady) 32 | return true; 33 | if(val != n) { 34 | //System.out.printf("not ready to consume: %d != %d: %d%n",val,n,id); 35 | return false; 36 | } 37 | return alwaysReady || readyToConsume; 38 | } 39 | 40 | void produce(int n) { 41 | if(alwaysReady) 42 | return; 43 | //System.out.println("produce: "+n+","+id); 44 | readyToProduce = false; 45 | readyToConsume = true; 46 | assert n >= val: ""+n+" >= "+val; 47 | val = n; 48 | } 49 | 50 | void consume(int n) { 51 | if(alwaysReady) 52 | return; 53 | //System.out.println("consume: "+n+","+id); 54 | readyToProduce = true; 55 | readyToConsume = false; 56 | } 57 | } 58 | 59 | class Segment { 60 | final static boolean ALL_ = true; 61 | final static int N_STEPS = 100; 62 | final static int N_SEGS = 100; 63 | 64 | final int id; 65 | 66 | GuardVar< ProdCon> left = new GuardVar< ProdCon>(new ProdCon(false)); 67 | GuardVar< ProdCon> right = new GuardVar< ProdCon>(new ProdCon(false)); 68 | GuardVar< ProdCon> neighborLeft, neighborRight; 69 | public String toString() { 70 | return ""+id+"{"+ 71 | left.getGuard().id+","+ 72 | right.getGuard().id+","+ 73 | neighborLeft.getGuard().id+","+ 74 | neighborRight.getGuard().id+ 75 | "}"; 76 | } 77 | 78 | Segment(int id) { this.id = id; } 79 | 80 | volatile static boolean complete = false; 81 | 82 | void runStep(final int step) { 83 | if(step == N_STEPS) { 84 | if(id == 0) { 85 | System.out.println("Complete!"); 86 | } 87 | complete = true; 88 | return; 89 | } 90 | if(id == 0) 91 | System.out.println("Running step: " + step+" id="+id); 92 | //condition with(left => l, right => r) 93 | Guard.runCondition(left, right, new CondCheck2<>() { 94 | public boolean check(Var l_, Var r_) { 95 | ProdCon l = l_.get(); 96 | ProdCon r = r_.get(); 97 | //assert this guardedby left.getGuard(); 98 | //assert this guardedby right.getGuard(); 99 | if (!l.isReadyToConsume(step)) { 100 | return false; 101 | } 102 | if (!r.isReadyToConsume(step)) { 103 | return false; 104 | } 105 | //System.out.printf("Stage1: step=%d, id=%d%n",step,id); 106 | l.consume(step); 107 | r.consume(step); 108 | assert r.id != l.id; 109 | if(ALL_) { 110 | left.signalAll(); 111 | right.signalAll(); 112 | } else { 113 | left.signal(); 114 | right.signal(); 115 | } 116 | //ignore { Thread.sleep(100); } 117 | //condition with(neighborLeft => nl, neighborRight => nr) 118 | Guard.runCondition(neighborLeft, neighborRight, new CondCheck2<>() 119 | { 120 | @Override 121 | public boolean check(Var nl_, Var nr_) { 122 | ProdCon nl = nl_.get(); 123 | ProdCon nr = nr_.get(); 124 | //assert this guardedby neighborLeft.getGuard(); 125 | //assert this guardedby neighborRight.getGuard(); 126 | if (!nl.isReadyToProduce(step)) { 127 | return false; 128 | } 129 | if (!nr.isReadyToProduce(step)) { 130 | return false; 131 | } 132 | //System.out.printf("Stage2: step=%d, id=%d%n",step,id); 133 | nl.produce(step + 1); 134 | nr.produce(step + 1); 135 | assert nl.id != nr.id: "on seg: "+id; 136 | if(ALL_) { 137 | neighborLeft.signalAll(); 138 | neighborRight.signalAll(); 139 | } else { 140 | neighborLeft.signal(); 141 | neighborRight.signal(); 142 | } 143 | runStep(step + 1); 144 | 145 | return true; 146 | } 147 | }); 148 | return true; 149 | } 150 | }); 151 | } 152 | } 153 | 154 | public class March { 155 | 156 | public static void main(String[] args) { 157 | Test.requireAssert(); 158 | System.out.println("Segment.N_SEGS=" + Segment.N_SEGS); 159 | final List< Segment> segs = new ArrayList<>(); 160 | for (int i = 0; i < Segment.N_SEGS; i++) { 161 | segs.add(new Segment(i)); 162 | } 163 | 164 | for (int i = 0; i < Segment.N_SEGS; i++) { 165 | Segment seg = segs.get(i); 166 | if (i == 0) { 167 | seg.left = seg.neighborLeft = new GuardVar< ProdCon>(new ProdCon(true)); 168 | } else { 169 | seg.neighborLeft = segs.get(i - 1).right; 170 | } 171 | 172 | if (i + 1 == Segment.N_SEGS) { 173 | seg.right = seg.neighborRight = new GuardVar< ProdCon>(new ProdCon(true)); 174 | } else { 175 | seg.neighborRight = segs.get(i + 1).left; 176 | } 177 | 178 | System.out.println("seg: "+seg); 179 | } 180 | 181 | for (int i = 0; i < Segment.N_SEGS; i++) { 182 | final Segment seg = segs.get(i); 183 | seg.runStep(0); 184 | } 185 | Pool.await(); 186 | assert Segment.complete; 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /src/edu/lsu/cct/javalineer/Guard.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package edu.lsu.cct.javalineer; 7 | 8 | import java.util.*; 9 | import java.util.concurrent.CompletableFuture; 10 | import java.util.concurrent.atomic.AtomicInteger; 11 | import java.util.concurrent.atomic.AtomicReference; 12 | 13 | /** 14 | * 15 | * @author sbrandt 16 | */ 17 | public class Guard implements Comparable { 18 | static AtomicInteger idSeq = new AtomicInteger(0); 19 | public final int id = idSeq.getAndIncrement(); 20 | 21 | public int compareTo(Guard g) { 22 | return id - g.id; 23 | } 24 | 25 | public String toString() { 26 | return "Guard("+id+")"; 27 | } 28 | 29 | public Guard getGuard() { 30 | return this; 31 | } 32 | 33 | AtomicReference task = new AtomicReference<>(null); 34 | 35 | public static boolean has(Guard g) { 36 | TreeSet ts = GuardTask.GUARDS_HELD.get(); 37 | if(ts == null) return false; 38 | return ts.contains(g); 39 | } 40 | 41 | public static boolean has(TreeSet guards) { 42 | TreeSet ts = GuardTask.GUARDS_HELD.get(); 43 | if (ts == null) { 44 | return false; 45 | } 46 | return ts.containsAll(guards); 47 | } 48 | 49 | public void runGuarded(Runnable r) { 50 | TreeSet tg = new TreeSet<>(); 51 | tg.add(this); 52 | runGuarded(tg, r); 53 | } 54 | 55 | public void nowOrNever(Runnable r) { 56 | TreeSet tg = new TreeSet<>(); 57 | tg.add(this); 58 | nowOrNever(tg, r); 59 | } 60 | 61 | public void nowOrElse(Runnable r, Runnable orElse) { 62 | TreeSet tg = new TreeSet<>(); 63 | tg.add(this); 64 | nowOrElse(tg, r, orElse); 65 | } 66 | 67 | public static void runGuarded(Guard g, Runnable r) { 68 | g.runGuarded(r); 69 | } 70 | 71 | public static void runGuarded(final GuardVar g, final GuardTask1 c) { 72 | g.runGuarded(()->{ c.run(g.var); }); 73 | } 74 | 75 | public static void runGuarded(final GuardVar g1,final GuardVar g2, final GuardTask2 c) { 76 | final TreeSet ts = new TreeSet<>(); 77 | ts.add(g1); 78 | ts.add(g2); 79 | Guard.runGuarded(ts,()->{ c.run(g1.var,g2.var); }); 80 | } 81 | 82 | public static void runGuarded( 83 | final GuardVar g1, 84 | final GuardVar g2, 85 | final GuardVar g3, 86 | final GuardTask3 c) { 87 | final TreeSet ts = new TreeSet<>(); 88 | ts.add(g1); 89 | ts.add(g2); 90 | ts.add(g3); 91 | Guard.runGuarded(ts,()->{ c.run(g1.var,g2.var,g3.var); }); 92 | } 93 | 94 | public static void runGuarded( 95 | final GuardVar g1, 96 | final GuardVar g2, 97 | final GuardVar g3, 98 | final GuardVar g4, 99 | final GuardTask4 c) { 100 | final TreeSet ts = new TreeSet<>(); 101 | ts.add(g1); 102 | ts.add(g2); 103 | ts.add(g3); 104 | ts.add(g4); 105 | Guard.runGuarded(ts, () -> c.run(g1.var, g2.var, g3.var, g4.var)); 106 | } 107 | 108 | public static void nowOrNever(final GuardVar g, final GuardTask1 c) { 109 | g.nowOrNever(() -> c.run(g.var)); 110 | } 111 | 112 | public static void nowOrNever(final GuardVar g1, final GuardVar g2, final GuardTask2 c) { 113 | Guard.nowOrNever(new TreeSet<>() {{ add(g1); add(g2); }}, () -> c.run(g1.var, g2.var)); 114 | } 115 | 116 | public static void nowOrNever( 117 | final GuardVar g1, 118 | final GuardVar g2, 119 | final GuardVar g3, 120 | final GuardTask3 c) { 121 | Guard.nowOrNever(new TreeSet<>() {{ add(g1); add(g2); add(g3); }}, () -> c.run(g1.var, g2.var, g3.var)); 122 | } 123 | 124 | public static void nowOrElse(final GuardVar g, final GuardTask1 c, final Runnable orElse) { 125 | g.nowOrElse(() -> c.run(g.var), orElse); 126 | } 127 | 128 | public static void nowOrElse(final GuardVar g1, final GuardVar g2, final GuardTask2 c, final Runnable orElse) { 129 | Guard.nowOrElse(new TreeSet<>() {{ add(g1); add(g2); }}, () -> c.run(g1.var, g2.var), orElse); 130 | } 131 | 132 | public static void nowOrElse(final GuardVar g1, 133 | final GuardVar g2, 134 | final GuardVar g3, 135 | final GuardTask3 c, 136 | final Runnable orElse) { 137 | Guard.nowOrElse(new TreeSet<>() {{ add(g1); add(g2); add(g3); }}, () -> c.run(g1.var, g2.var, g3.var), orElse); 138 | } 139 | 140 | private static CompletableFuture setNow(final GuardVar gv, final AtomicReference>> ref) { 141 | final var fut = new CompletableFuture(); 142 | gv.nowOrElse(() -> { 143 | ref.set(Optional.of(gv.var)); 144 | fut.complete(null); 145 | }, () -> { 146 | ref.set(Optional.empty()); 147 | fut.complete(null); 148 | }); 149 | return fut; 150 | } 151 | 152 | public static void now(final GuardVar g, final OptionalGuardTask1 c) { 153 | g.nowOrElse(() -> c.run(Optional.of(g.var)), () -> c.run(Optional.empty())); 154 | } 155 | 156 | public static void now(final GuardVar g1, final GuardVar g2, final OptionalGuardTask2 c) { 157 | final var o1 = new AtomicReference>>(); 158 | final var o2 = new AtomicReference>>(); 159 | 160 | CompletableFuture.allOf(setNow(g1, o1), setNow(g2, o2)) 161 | .thenRun(() -> Guard.runAlways(new TreeSet<>() {{ add(g1); add(g2); }}, 162 | () -> c.run(o1.get(), o2.get()))); 163 | } 164 | 165 | public static void now(final GuardVar g1, 166 | final GuardVar g2, 167 | final GuardVar g3, 168 | final OptionalGuardTask3 c) { 169 | final var o1 = new AtomicReference>>(); 170 | final var o2 = new AtomicReference>>(); 171 | final var o3 = new AtomicReference>>(); 172 | 173 | CompletableFuture.allOf(setNow(g1, o1), setNow(g2, o2), setNow(g3, o3)) 174 | .thenRun(() -> Guard.runAlways(new TreeSet<>() {{ add(g1); add(g2); add(g3); }}, 175 | () -> c.run(o1.get(), o2.get(), o3.get()))); 176 | } 177 | 178 | public static void now(final GuardVar g1, 179 | final GuardVar g2, 180 | final GuardVar g3, 181 | final GuardVar g4, 182 | final OptionalGuardTask4 c) { 183 | final var o1 = new AtomicReference>>(); 184 | final var o2 = new AtomicReference>>(); 185 | final var o3 = new AtomicReference>>(); 186 | final var o4 = new AtomicReference>>(); 187 | 188 | CompletableFuture.allOf(setNow(g1, o1), setNow(g2, o2), setNow(g3, o3), setNow(g4, o4)) 189 | .thenRun(() -> Guard.runAlways(new TreeSet<>() {{ add(g1); add(g2); add(g3); add(g4); }}, 190 | () -> c.run(o1.get(), o2.get(), o3.get(), o4.get()))); 191 | } 192 | 193 | public static void runGuarded(TreeSet gset, Runnable r) { 194 | GuardTask gt = new GuardTask(gset,r); 195 | gt.run(); 196 | } 197 | 198 | public static void nowOrNever(Guard g, Runnable r) { 199 | nowOrNever(new TreeSet<>() {{add(g);}}, r); 200 | } 201 | 202 | public static void nowOrNever(TreeSet gSet, Runnable r) { 203 | GuardTask gt = new GuardTask(gSet, () -> { 204 | if (Guard.has(gSet)) { 205 | r.run(); 206 | } 207 | }); 208 | gt.runImmediately(); 209 | } 210 | 211 | /* 212 | * This is private because we only want it called from inside Guard#now. 213 | */ 214 | private static void runAlways(TreeSet gSet, Runnable r) { 215 | GuardTask gt = new GuardTask(gSet, r); 216 | gt.runImmediately(); 217 | } 218 | 219 | public static void nowOrElse(TreeSet gSet, Runnable r, Runnable orElse) { 220 | GuardTask gt = new GuardTask(gSet, () -> { 221 | if (Guard.has(gSet)) { 222 | r.run(); 223 | } else { 224 | orElse.run(); 225 | } 226 | }); 227 | gt.runImmediately(); 228 | } 229 | 230 | public static void nowOrElse(Guard g, Runnable r, Runnable orElse) { 231 | nowOrElse(new TreeSet<>() {{ add(g); }}, r, orElse); 232 | } 233 | 234 | CondMgr cmgr = new CondMgr(); 235 | 236 | public void signal() { 237 | cmgr.signal(); 238 | } 239 | 240 | public void signalAll() { 241 | cmgr.signalAll(); 242 | } 243 | 244 | public static CompletableFuture runCondition( 245 | GuardVar gv, 246 | final CondCheck1 c) { 247 | return Guard.runCondition(gv,new CondTask1(c)); 248 | } 249 | 250 | public static CompletableFuture runCondition( 251 | GuardVar gv, 252 | final CondTask1 c) { 253 | TreeSet ts = new TreeSet<>(); 254 | ts.add(gv); 255 | c.set1(gv.var); 256 | return runCondition(ts,c); 257 | } 258 | 259 | public static CompletableFuture runCondition( 260 | GuardVar gv1, 261 | GuardVar gv2, 262 | final CondCheck2 c) { 263 | return Guard.runCondition(gv1,gv2,new CondTask2(c)); 264 | } 265 | 266 | public static CompletableFuture runCondition( 267 | GuardVar gv1, 268 | GuardVar gv2, 269 | final CondTask2 c) { 270 | TreeSet ts = new TreeSet<>(); 271 | ts.add(gv1); 272 | ts.add(gv2); 273 | c.set1(gv1.var); 274 | c.set2(gv2.var); 275 | return runCondition(ts,c); 276 | } 277 | 278 | public static CompletableFuture runCondition( 279 | GuardVar gv1, 280 | GuardVar gv2, 281 | GuardVar gv3, 282 | final CondCheck3 c) { 283 | return Guard.runCondition(gv1,gv2,gv3,new CondTask3(c)); 284 | } 285 | 286 | public static CompletableFuture runCondition( 287 | GuardVar gv1, 288 | GuardVar gv2, 289 | GuardVar gv3, 290 | final CondTask3 c) { 291 | TreeSet ts = new TreeSet<>(); 292 | ts.add(gv1); 293 | ts.add(gv2); 294 | ts.add(gv3); 295 | c.set1(gv1.var); 296 | c.set2(gv2.var); 297 | c.set3(gv3.var); 298 | return runCondition(ts,c); 299 | } 300 | 301 | public static CompletableFuture runCondition(final TreeSet ts,final CondTask c) { 302 | assert ts.size() > 0; 303 | Cond cond = new Cond(); 304 | cond.task = c; 305 | cond.gset = ts; 306 | for(Guard g : ts) 307 | g.cmgr.add(new CondLink(cond)); 308 | Guard.runGuarded(ts,c); 309 | return cond.task.fut; 310 | } 311 | } 312 | --------------------------------------------------------------------------------