From: Fredrik Tolf Date: Fri, 25 Feb 2022 16:39:51 +0000 (+0100) Subject: Added some kind of environment handling. X-Git-Url: http://git.dolda2000.com/gitweb/?a=commitdiff_plain;h=4e6705bd163a303c3ffb5e306162cbd7660b8dd8;p=jrw.git Added some kind of environment handling. --- diff --git a/src/jrw/Dispatch.java b/src/jrw/Dispatch.java index d08867c..10b0909 100644 --- a/src/jrw/Dispatch.java +++ b/src/jrw/Dispatch.java @@ -4,11 +4,13 @@ import java.util.*; public class Dispatch { public static Map handle(Handler handler, Request req) { - while(true) { - try { - return(handler.handle(req)); - } catch(Restart r) { - handler = r; + try(Environment.Frame f = new Environment().frame()) { + while(true) { + try { + return(handler.handle(req)); + } catch(Restart r) { + handler = r; + } } } } diff --git a/src/jrw/Environment.java b/src/jrw/Environment.java new file mode 100644 index 0000000..a93b149 --- /dev/null +++ b/src/jrw/Environment.java @@ -0,0 +1,85 @@ +package jrw; + +import java.util.*; +import java.util.function.*; + +public class Environment { + public static final Environment root = new Environment(); + private static final ThreadLocal current = new ThreadLocal<>(); + public final Environment parent; + private Map, Object> data = Collections.emptyMap(); + + public static class Variable { + private final Supplier ival; + private T rval; + private boolean inited; + + public Variable(Supplier ival) { + this.ival = ival; + } + + @SuppressWarnings("unchecked") + public T get() { + for(Environment env = current(); env != null; env = env.parent) { + Map, Object> data = env.data; + if(data.containsKey(this)) + return((T)data.get(this)); + } + if(!inited) { + synchronized(this) { + if(!inited) { + rval = (this.ival == null) ? null : this.ival.get(); + inited = true; + } + } + } + return(rval); + } + } + + public Environment(Environment parent) { + this.parent = parent; + } + + public Environment() { + this(current()); + } + + public void set(Variable var, T val) { + synchronized(this) { + Map, Object> data = new IdentityHashMap<>(this.data); + data.put(var, val); + this.data = data; + } + } + + public void clear(Variable var, T val) { + synchronized(this) { + Map, Object> data = new IdentityHashMap<>(this.data); + data.remove(var); + this.data = data; + } + } + + public static Environment current() { + Environment ret = current.get(); + return((ret == null) ? root : ret); + } + + public class Frame implements AutoCloseable { + private final Environment prev; + + private Frame() { + this.prev = current.get(); + current.set(Environment.this); + } + + public void close() { + current.set(prev); + } + } + + public Frame frame() { + return(new Frame()); + } +}