/* This class is thread-safe, and optimized for more parallelism. E.g., we can run incUpper and decLower at the same time. */ public class RangeOpt { private int lower; private Object lowerLock = new Object(); // guards lower private int upper; private Object upperLock = new Object(); // guards upper // INVARIANT: lowerLock acquired before upperLock to avoid deadlock // INVARIANT: lower <= upper private boolean invariantOK(int l, int u) { return l <= u; } public RangeOpt(int lower, int upper) throws IllegalArgumentException { if (!invariantOK(lower,upper)) throw new IllegalArgumentException(); this.lower = lower; this.upper = upper; } public boolean inRange(int v) { synchronized (lowerLock) { synchronized (upperLock) { if (v >= lower && v <= upper) return true; return false; } } } public void incUpper() { synchronized (upperLock) { upper ++; } } public void incLower() throws IllegalArgumentException { synchronized (lowerLock) { synchronized (upperLock) { if (!invariantOK(lower+1,upper)) throw new IllegalArgumentException(); lower ++; } } } public void decLower() { synchronized (lowerLock) { lower-- ; } } public void decUpper() throws IllegalArgumentException { synchronized (lowerLock) { synchronized (upperLock) { if (!invariantOK(lower,upper-1)) throw new IllegalArgumentException(); upper --; } } } }