/* This file is part of the db4o object database http://www.db4o.com Copyright (C) 2004 - 2011 Versant Corporation http://www.versant.com db4o is free software; you can redistribute it and/or modify it under the terms of version 3 of the GNU General Public License as published by the Free Software Foundation. db4o is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/. */ package com.db4o.foundation; /** * @exclude */ public class BlockingQueue<T> implements BlockingQueue4<T> { protected NonblockingQueue<T> _queue = new NonblockingQueue<T>(); protected Lock4 _lock = new Lock4(); protected boolean _stopped; public void add(final T obj) { if(obj == null){ throw new IllegalArgumentException(); } _lock.run(new Closure4<Void>() { public Void run() { _queue.add(obj); _lock.awake(); return null; } }); } public boolean hasNext() { return _lock.run(new Closure4<Boolean>() { public Boolean run() { return _queue.hasNext(); } }); } public Iterator4<T> iterator() { return _lock.run(new Closure4<Iterator4<T>>() { public Iterator4<T> run() { return _queue.iterator(); } }); } public T next(final long timeout) throws BlockingQueueStoppedException { return (T) _lock.run(new Closure4<T>() { public T run() { return unsafeWaitForNext(timeout) ? unsafeNext() : null; } }); } public int drainTo(final Collection4<T> target) { return _lock.run(new Closure4<Integer>() { public Integer run() { unsafeWaitForNext(); int i = 0; while(hasNext()) { i++; target.add(unsafeNext()); } return i; } }); } public boolean waitForNext(final long timeout) throws BlockingQueueStoppedException { return _lock.run(new Closure4<Boolean>() { public Boolean run() { return unsafeWaitForNext(timeout); } }); } public T next() throws BlockingQueueStoppedException { return (T) _lock.run(new Closure4<T>() { public T run() { unsafeWaitForNext(); return unsafeNext(); } }); } public void stop(){ _lock.run(new Closure4<Void>() { public Void run() { _stopped = true; _lock.awake(); return null; } }); } public T nextMatching(final Predicate4<T> condition) { return _lock.run(new Closure4<T>() { public T run() { return _queue.nextMatching(condition); } }); } public void waitForNext() throws BlockingQueueStoppedException { _lock.run(new Closure4<Boolean>() { public Boolean run() { unsafeWaitForNext(); return null; } }); } protected void unsafeWaitForNext() throws BlockingQueueStoppedException { unsafeWaitForNext(Long.MAX_VALUE); } protected boolean unsafeWaitForNext(final long timeout) throws BlockingQueueStoppedException { long timeLeft = timeout; long now = System.currentTimeMillis(); while (timeLeft > 0) { if (_queue.hasNext()) { return true; } if(_stopped) { throw new BlockingQueueStoppedException(); } _lock.snooze(timeLeft); long l = now; now = System.currentTimeMillis(); timeLeft -= now-l; } return false; } private T unsafeNext() { return _queue.next(); } }