package linda.shm; import linda.Callback; import linda.Linda; import linda.Tuple; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; class Reveil implements Callback { Lock lock = new ReentrantLock(); Tuple template; Condition condition; Reveil(Tuple template) { this.template = template; this.condition = lock.newCondition(); } public void call(Tuple t) { return; } void sleep() { try { lock.lock(); condition.await(); lock.unlock(); } catch (InterruptedException e) { e.printStackTrace(); } } void reveil(Tuple t) { if (t.matches(this.template)) { lock.lock(); condition.signal(); lock.unlock(); } } } /** Shared memory implementation of Linda. */ public class CentralizedLinda implements Linda { List tuples; List reveils; public CentralizedLinda() { this.tuples = Collections.synchronizedList(new ArrayList()); this.reveils = Collections.synchronizedList(new ArrayList()); } /** * Insert a tuple into the tuple list. (non-blocking) * * @param template the Tuple template your looking for */ public void write(Tuple t) { tuples.add(t); reveils.forEach(r -> r.reveil(t)); } /** * Extract the tuple from the tuple list. (blocking) * * @param template the Tuple template your looking for */ public Tuple take(Tuple template) { Reveil reveil = new Reveil(template); reveils.add(reveil); Tuple result = null; result = tryTake(template); while (result == null) { reveil.sleep(); result = tryTake(template); } return result; } /** * Get the tuple from the tuple list. (blocking) * * @param template the Tuple template your looking for */ public Tuple read(Tuple template) { Reveil reveil = new Reveil(template); reveils.add(reveil); Tuple result = null; result = tryRead(template); while (result == null) { reveil.sleep(); result = tryRead(template); } return result; } /** * Extract the tuple from the tuple list. (non-blocking) * * @param template the Tuple template your looking for */ public Tuple tryTake(Tuple template) { Iterator iterator = tuples.iterator(); Tuple next = null; while (iterator.hasNext()) { next = iterator.next(); if (next.matches(template)) { iterator.remove(); break; } } return next; } /** * Get the tuple from the tuple list. (non-blocking) * * @param template the Tuple template your looking for */ public Tuple tryRead(Tuple template) { Iterator iterator = tuples.iterator(); Tuple next = null; while (iterator.hasNext()) { next = iterator.next(); if (next.matches(template)) { break; } } return next; } /** * Extract the tuples in the tuple list. (blocking) * * @param template the Tuple template your looking for */ public Collection takeAll(Tuple template) { List results = new ArrayList(); Tuple result = new Tuple(); while (result != null) { result = tryTake(template); if (result != null) { results.add(result); } } return results; } /** * Extract the tuples in the tuple list. (blocking) * * @param template the Tuple template your looking for */ public Collection readAll(Tuple template) { List results = new ArrayList(); Iterator iterator = tuples.iterator(); Tuple next = null; while (iterator.hasNext()) { next = iterator.next(); if (next.matches(template)) { results.add(next); } } return results; } public void eventRegister(eventMode mode, eventTiming timing, Tuple template, Callback callback) { new Thread() { public void run() { switch (timing) { case IMMEDIATE: callback.call(mode == eventMode.READ ? read(template) : take(template)); return; case FUTURE: List knownTuples = (List) readAll(template); callback.call(tryRTknown(template, knownTuples, mode)); return; } } }.start(); } private Tuple tryRTknown(Tuple template, List knownTuples, eventMode mode) { Reveil reveil = new Reveil(template); reveils.add(reveil); Tuple result = null; for (int i = 0; i < tuples.size(); i++) { result = mode == eventMode.READ ? tuples.get(i) : tuples.remove(i); if (result.matches(template)) { return result; } } while (result == null) { reveil.sleep(); for (int i = 0; i < tuples.size(); i++) { result = mode == eventMode.READ ? tuples.get(i) : tuples.remove(i); if (result.matches(template)) { return result; } } } return result; } public void debug(String prefix) { System.out.println(prefix + tuples); } }