package freenet.support.io; import java.io.DataOutputStream; import java.io.IOException; import freenet.client.async.ClientContext; import freenet.support.api.LockableRandomAccessBuffer; public class BarrierRandomAccessBuffer implements LockableRandomAccessBuffer { private final LockableRandomAccessBuffer underlying; private boolean proceed; private int waiting; public BarrierRandomAccessBuffer(LockableRandomAccessBuffer underlying) { this.underlying = underlying; proceed = true; } @Override public long size() { return underlying.size(); } /** Wait until some threads are waiting for the proceed thread. */ public void waitForWaiting() { synchronized(this) { if(proceed) throw new IllegalArgumentException(); while(waiting == 0) { try { wait(); } catch (InterruptedException e) { // Ignore. } } } } /** Wait until the proceed flag is set. */ private void waitForClear() { synchronized(this) { waiting++; if(waiting == 1) notifyAll(); while(!proceed) { try { wait(); } catch (InterruptedException e) { // Ignore. } } waiting--; } } @Override public void pread(long fileOffset, byte[] buf, int bufOffset, int length) throws IOException { waitForClear(); underlying.pread(fileOffset, buf, bufOffset, length); } @Override public void pwrite(long fileOffset, byte[] buf, int bufOffset, int length) throws IOException { waitForClear(); underlying.pwrite(fileOffset, buf, bufOffset, length); } @Override public void close() { underlying.close(); } @Override public void free() { underlying.free(); } @Override public RAFLock lockOpen() throws IOException { return underlying.lockOpen(); } @Override public void onResume(ClientContext context) throws ResumeFailedException { throw new UnsupportedOperationException(); } @Override public void storeTo(DataOutputStream dos) throws IOException { throw new UnsupportedOperationException(); } public synchronized void proceed() { proceed = true; notifyAll(); } public synchronized void pause() { proceed = false; } @Override public int hashCode() { return underlying.hashCode(); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } BarrierRandomAccessBuffer other = (BarrierRandomAccessBuffer) obj; return underlying.equals(other.underlying); } }