blob: d89d60a07a4eedd7090a39fcd4b893d19fb0876b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2015 Oracle. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0, which accompanies this distribution
* and is available at http://www.eclipse.org/legal/epl-v10.html.
*
* Contributors:
* Oracle - initial API and implementation
******************************************************************************/
package org.eclipse.jpt.common.utility.internal.deque;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import org.eclipse.jpt.common.utility.command.Command;
import org.eclipse.jpt.common.utility.internal.collection.MapTools;
import org.eclipse.jpt.common.utility.deque.Deque;
import org.eclipse.jpt.common.utility.stack.Stack;
import org.eclipse.jpt.common.utility.transformer.Transformer;
/**
* Thread-safe implementation of the {@link Deque} interface.
* This also provides protocol for suspending a thread until the
* deque is empty or not empty, with optional time-outs.
* @param <E> the type of elements maintained by the deque
* @see DequeTools
*/
public class SynchronizedDeque<E>
implements Deque<E>, Serializable
{
/** Backing deque. */
private final Deque<E> deque;
/** Object to synchronize on. */
private final Object mutex;
private static final long serialVersionUID = 1L;
// ********** constructors **********
/**
* Construct a synchronized deque that wraps the
* specified deque and locks on the specified mutex.
*/
public SynchronizedDeque(Deque<E> deque, Object mutex) {
super();
if ((deque == null) || (mutex == null)) {
throw new NullPointerException();
}
this.deque = deque;
this.mutex = mutex;
}
/**
* Construct a synchronized deque that wraps the
* specified deque and locks on itself.
*/
public SynchronizedDeque(Deque<E> deque) {
super();
if (deque == null) {
throw new NullPointerException();
}
this.deque = deque;
this.mutex = this;
}
// ********** Deque implementation **********
public void enqueueTail(E element) {
synchronized (this.mutex) {
this.enqueueTail_(element);
}
}
/**
* Pre-condition: synchronized
*/
private void enqueueTail_(E element) {
this.deque.enqueueTail(element);
this.mutex.notifyAll();
}
public void enqueueHead(E element) {
synchronized (this.mutex) {
this.enqueueHead_(element);
}
}
/**
* Pre-condition: synchronized
*/
private void enqueueHead_(E element) {
this.deque.enqueueHead(element);
this.mutex.notifyAll();
}
public E dequeueHead() {
synchronized (this.mutex) {
return this.dequeueHead_();
}
}
/**
* Pre-condition: synchronized
*/
private E dequeueHead_() {
E element = this.deque.dequeueHead();
this.mutex.notifyAll();
return element;
}
public E dequeueTail() {
synchronized (this.mutex) {
return this.dequeueTail_();
}
}
/**
* Pre-condition: synchronized
*/
private E dequeueTail_() {
E element = this.deque.dequeueTail();
this.mutex.notifyAll();
return element;
}
public E peekHead() {
synchronized (this.mutex) {
return this.deque.peekHead();
}
}
public E peekTail() {
synchronized (this.mutex) {
return this.deque.peekTail();
}
}
public boolean isEmpty() {
synchronized (this.mutex) {
return this.deque.isEmpty();
}
}
// ********** indefinite waits **********
/**
* Suspend the current thread until the deque's empty status changes
* to the specified value.
*/
public void waitUntilEmptyIs(boolean empty) throws InterruptedException {
synchronized (this.mutex) {
this.waitUntilEmptyIs_(empty);
}
}
/**
* Pre-condition: synchronized
*/
private void waitUntilEmptyIs_(boolean empty) throws InterruptedException {
while (this.deque.isEmpty() != empty) {
this.mutex.wait();
}
}
/**
* Suspend the current thread until the deque is empty.
*/
public void waitUntilEmpty() throws InterruptedException {
this.waitUntilEmptyIs(true);
}
/**
* Suspend the current thread until the deque has something on it.
*/
public void waitUntilNotEmpty() throws InterruptedException {
this.waitUntilEmptyIs(false);
}
/**
* Suspend the current thread until the deque is empty,
* then "enqueue" the specified item to the tail of the deque
* and continue executing.
*/
public void waitToEnqueueTail(E element) throws InterruptedException {
synchronized (this.mutex) {
this.waitUntilEmptyIs_(true);
this.enqueueTail_(element);
}
}
/**
* Suspend the current thread until the deque is empty,
* then "enqueue" the specified item to the head of the deque
* and continue executing.
*/
public void waitToEnqueueHead(E element) throws InterruptedException {
synchronized (this.mutex) {
this.waitUntilEmptyIs_(true);
this.enqueueHead_(element);
}
}
/**
* Suspend the current thread until the deque has something on it,
* then "dequeue" an item from the head of the deque and return it.
*/
public Object waitToDequeueHead() throws InterruptedException {
synchronized (this.mutex) {
this.waitUntilEmptyIs_(false);
return this.dequeueHead_();
}
}
/**
* Suspend the current thread until the deque has something on it,
* then "dequeue" an item from the tail of the deque and return it.
*/
public Object waitToDequeueTail() throws InterruptedException {
synchronized (this.mutex) {
this.waitUntilEmptyIs_(false);
return this.dequeueTail_();
}
}
// ********** timed waits **********
/**
* Suspend the current thread until the deque's empty status changes
* to the specified value or the specified time-out occurs.
* The time-out is specified in milliseconds. Return <code>true</code> if the specified
* empty status was achieved; return <code>false</code> if a time-out occurred.
* If the deque's empty status is already the specified value,
* return <code>true</code> immediately.
* If the time-out is zero, wait indefinitely.
*/
public boolean waitUntilEmptyIs(boolean empty, long timeout) throws InterruptedException {
synchronized (this.mutex) {
return this.waitUntilEmptyIs_(empty, timeout);
}
}
/**
* Pre-condition: synchronized
*/
private boolean waitUntilEmptyIs_(boolean empty, long timeout) throws InterruptedException {
if (timeout == 0L) {
this.waitUntilEmptyIs_(empty); // wait indefinitely until notified
return true; // if it ever comes back, the condition was met
}
long stop = System.currentTimeMillis() + timeout;
long remaining = timeout;
while ((this.deque.isEmpty() != empty) && (remaining > 0L)) {
this.mutex.wait(remaining);
remaining = stop - System.currentTimeMillis();
}
return (this.deque.isEmpty() == empty);
}
/**
* Suspend the current thread until the deque is empty
* or the specified time-out occurs.
* The time-out is specified in milliseconds. Return <code>true</code> if
* the deque is empty; return <code>false</code> if a time-out occurred.
* If the deque is already empty, return <code>true</code> immediately.
* If the time-out is zero, wait indefinitely.
*/
public boolean waitUntilEmpty(long timeout) throws InterruptedException {
return this.waitUntilEmptyIs(true, timeout);
}
/**
* Suspend the current thread until the deque has something on it.
* or the specified time-out occurs.
* The time-out is specified in milliseconds. Return <code>true</code> if
* the deque is not empty; return <code>false</code> if a time-out occurred.
* If the deque already has something on it, return <code>true</code> immediately.
* If the time-out is zero, wait indefinitely.
*/
public boolean waitUntilNotEmpty(long timeout) throws InterruptedException {
return this.waitUntilEmptyIs(false, timeout);
}
/**
* Suspend the current thread until the deque is empty,
* then "enqueue" the specified item to the tail of the deque
* and continue executing. If the deque is not emptied out
* before the time-out, simply continue executing without
* "enqueueing" the item.
* The time-out is specified in milliseconds. Return <code>true</code> if the
* item was enqueued; return <code>false</code> if a time-out occurred.
* If the deque is already empty, "enqueue" the specified item and
* return <code>true</code> immediately.
* If the time-out is zero, wait indefinitely.
*/
public boolean waitToEnqueueTail(E element, long timeout) throws InterruptedException {
synchronized (this.mutex) {
boolean success = this.waitUntilEmptyIs_(true, timeout);
if (success) {
this.enqueueTail_(element);
}
return success;
}
}
/**
* Suspend the current thread until the deque is empty,
* then "enqueue" the specified item to the head of the deque
* and continue executing. If the deque is not emptied out
* before the time-out, simply continue executing without
* "enqueueing" the item.
* The time-out is specified in milliseconds. Return <code>true</code> if the
* item was enqueued; return <code>false</code> if a time-out occurred.
* If the deque is already empty, "enqueue" the specified item and
* return <code>true</code> immediately.
* If the time-out is zero, wait indefinitely.
*/
public boolean waitToEnqueueHead(E element, long timeout) throws InterruptedException {
synchronized (this.mutex) {
boolean success = this.waitUntilEmptyIs_(true, timeout);
if (success) {
this.enqueueHead_(element);
}
return success;
}
}
/**
* Suspend the current thread until the deque has something on it,
* then "dequeue" an item from the head of the deque and return it.
* If the deque is empty and nothing is "enqueued" on to it before the
* time-out, throw a no such element exception.
* The time-out is specified in milliseconds.
* If the deque is not empty, "dequeue" an item and
* return it immediately.
* If the time-out is zero, wait indefinitely.
*/
public Object waitToDequeueHead(long timeout) throws InterruptedException {
synchronized (this.mutex) {
boolean success = this.waitUntilEmptyIs_(false, timeout);
if (success) {
return this.dequeueHead_();
}
throw new NoSuchElementException();
}
}
/**
* Suspend the current thread until the deque has something on it,
* then "dequeue" an item from the tail of the deque and return it.
* If the deque is empty and nothing is "enqueued" on to it before the
* time-out, throw a no such element exception.
* The time-out is specified in milliseconds.
* If the deque is not empty, "dequeue" an item and
* return it immediately.
* If the time-out is zero, wait indefinitely.
*/
public Object waitToDequeueTail(long timeout) throws InterruptedException {
synchronized (this.mutex) {
boolean success = this.waitUntilEmptyIs_(false, timeout);
if (success) {
return this.dequeueTail_();
}
throw new NoSuchElementException();
}
}
// ********** synchronized behavior **********
/**
* If the current thread is not interrupted, execute the specified command
* with the mutex locked. This is useful for initializing the deque in another
* thread.
*/
public void execute(Command command) throws InterruptedException {
if (Thread.currentThread().isInterrupted()) {
throw new InterruptedException();
}
synchronized (this.mutex) {
command.execute();
}
}
// ********** additional public protocol **********
/**
* "Enqueue" all the elements returned by the specified iterable to the deque's tail.
* Return whether the deque changed as a result.
*/
public boolean enqueueTailAll(Iterable<? extends E> iterable) {
return this.enqueueTailAll(iterable.iterator());
}
/**
* "Enqueue" all the elements returned by the specified iterable to the deque's head.
* Return whether the deque changed as a result.
*/
public boolean enqueueHeadAll(Iterable<? extends E> iterable) {
return this.enqueueHeadAll(iterable.iterator());
}
/**
* "Enqueue" all the elements returned by the specified iterator to the deque's tail.
* Return whether the deque changed as a result.
*/
public boolean enqueueTailAll(Iterator<? extends E> iterator) {
if ( ! iterator.hasNext()) {
return false;
}
synchronized (this.mutex) {
return this.enqueueTailAll_(iterator);
}
}
/**
* Pre-condition: synchronized
* Assume the iterator is not empty.
*/
private boolean enqueueTailAll_(Iterator<? extends E> iterator) {
do {
this.deque.enqueueTail(iterator.next());
} while (iterator.hasNext());
this.mutex.notifyAll();
return true;
}
/**
* "Enqueue" all the elements returned by the specified iterator to the deque's head.
* Return whether the deque changed as a result.
*/
public boolean enqueueHeadAll(Iterator<? extends E> iterator) {
if ( ! iterator.hasNext()) {
return false;
}
synchronized (this.mutex) {
return this.enqueueHeadAll_(iterator);
}
}
/**
* Pre-condition: synchronized
* Assume the iterator is not empty.
*/
private boolean enqueueHeadAll_(Iterator<? extends E> iterator) {
do {
this.deque.enqueueHead(iterator.next());
} while (iterator.hasNext());
this.mutex.notifyAll();
return true;
}
/**
* "Enqueue" all the elements in the specified array to the deque's tail.
* Return whether the deque changed as a result.
*/
public boolean enqueueTailAll(E... array) {
int len = array.length;
if (len == 0) {
return false;
}
synchronized (this.mutex) {
return this.enqueueTailAll_(array, len);
}
}
/**
* Pre-condition: synchronized
* Assume the array is not empty.
*/
private boolean enqueueTailAll_(E[] array, int arrayLength) {
int i = 0;
do {
this.deque.enqueueTail(array[i++]);
} while (i < arrayLength);
this.mutex.notifyAll();
return true;
}
/**
* "Enqueue" all the elements in the specified array to the deque's head.
* Return whether the deque changed as a result.
*/
public boolean enqueueHeadAll(E... array) {
int len = array.length;
if (len == 0) {
return false;
}
synchronized (this.mutex) {
return this.enqueueHeadAll_(array, len);
}
}
/**
* Pre-condition: synchronized
* Assume the array is not empty.
*/
private boolean enqueueHeadAll_(E[] array, int arrayLength) {
int i = 0;
do {
this.deque.enqueueHead(array[i++]);
} while (i < arrayLength);
this.mutex.notifyAll();
return true;
}
/**
* Pop all the elements from the specified stack and "enqueue" them to the deque's tail.
* Return whether the deque changed as a result.
*/
public boolean enqueueTailAll(Stack<? extends E> stack) {
if (stack.isEmpty()) {
return false;
}
synchronized (this.mutex) {
return this.enqueueTailAll_(stack);
}
}
/**
* Pre-condition: synchronized
* Assume the stack is not empty.
*/
private boolean enqueueTailAll_(Stack<? extends E> stack) {
do {
this.deque.enqueueTail(stack.pop());
} while ( ! stack.isEmpty());
this.mutex.notifyAll();
return true;
}
/**
* Pop all the elements from the specified stack and "enqueue" them to the deque's head.
* Return whether the deque changed as a result.
*/
public boolean enqueueHeadAll(Stack<? extends E> stack) {
if (stack.isEmpty()) {
return false;
}
synchronized (this.mutex) {
return this.enqueueHeadAll_(stack);
}
}
/**
* Pre-condition: synchronized
* Assume the stack is not empty.
*/
private boolean enqueueHeadAll_(Stack<? extends E> stack) {
do {
this.deque.enqueueHead(stack.pop());
} while ( ! stack.isEmpty());
this.mutex.notifyAll();
return true;
}
/**
* "Dequeue" all the elements from the specified deque's head and
* "enqueue" them to the deque's tail.
* Return whether the deque changed as a result.
* @see #drainHeadTo(Deque)
*/
public boolean enqueueTailAll(Deque<? extends E> q) {
if (q.isEmpty()) {
return false;
}
synchronized (this.mutex) {
return this.enqueueTailAll_(q);
}
}
/**
* Pre-condition: synchronized
* Assume the deque is not empty.
*/
private boolean enqueueTailAll_(Deque<? extends E> q) {
do {
this.deque.enqueueTail(q.dequeueHead());
} while ( ! q.isEmpty());
this.mutex.notifyAll();
return true;
}
/**
* "Dequeue" all the elements from the specified deque's tail and
* "enqueue" them to the deque's head.
* Return whether the deque changed as a result.
* @see #drainTailTo(Deque)
*/
public boolean enqueueHeadAll(Deque<? extends E> q) {
if (q.isEmpty()) {
return false;
}
synchronized (this.mutex) {
return this.enqueueHeadAll_(q);
}
}
/**
* Pre-condition: synchronized
* Assume the deque is not empty.
*/
private boolean enqueueHeadAll_(Deque<? extends E> q) {
do {
this.deque.enqueueHead(q.dequeueTail());
} while ( ! q.isEmpty());
this.mutex.notifyAll();
return true;
}
/**
* "Drain" all the current items from the deque's head and return them in a list.
*/
public ArrayList<E> drainHead() {
ArrayList<E> result = new ArrayList<E>();
this.drainHeadTo(result);
return result;
}
/**
* "Drain" all the current items from the deque's tail and return them in a list.
*/
public ArrayList<E> drainTail() {
ArrayList<E> result = new ArrayList<E>();
this.drainTailTo(result);
return result;
}
/**
* "Drain" all the current items from the deque's head into specified collection.
* Return whether the deque changed as a result.
*/
public boolean drainHeadTo(Collection<? super E> collection) {
synchronized (this.mutex) {
return this.drainHeadTo_(collection);
}
}
/**
* Pre-condition: synchronized
*/
private boolean drainHeadTo_(Collection<? super E> collection) {
if (this.deque.isEmpty()) {
return false;
}
return this.drainHeadTo__(collection);
}
/**
* Pre-condition: synchronized
* Assume the deque is not empty.
*/
private boolean drainHeadTo__(Collection<? super E> collection) {
do {
collection.add(this.deque.dequeueHead());
} while ( ! this.deque.isEmpty());
this.mutex.notifyAll();
return true;
}
/**
* "Drain" all the current items from the deque's tail into specified collection.
* Return whether the deque changed as a result.
*/
public boolean drainTailTo(Collection<? super E> collection) {
synchronized (this.mutex) {
return this.drainTailTo_(collection);
}
}
/**
* Pre-condition: synchronized
*/
private boolean drainTailTo_(Collection<? super E> collection) {
if (this.deque.isEmpty()) {
return false;
}
return this.drainTailTo__(collection);
}
/**
* Pre-condition: synchronized
* Assume the deque is not empty.
*/
private boolean drainTailTo__(Collection<? super E> collection) {
do {
collection.add(this.deque.dequeueTail());
} while ( ! this.deque.isEmpty());
this.mutex.notifyAll();
return true;
}
/**
* "Drain" all the current items from the deque's head into specified list
* at the specified index.
* Return whether the deque changed as a result.
*/
public boolean drainHeadTo(List<? super E> list, int index) {
synchronized (this.mutex) {
return this.drainHeadTo_(list, index);
}
}
/**
* Pre-condition: synchronized
*/
private boolean drainHeadTo_(List<? super E> list, int index) {
if (this.deque.isEmpty()) {
return false;
}
if (index == list.size()) {
return this.drainHeadTo__(list);
}
ArrayList<E> temp = new ArrayList<E>();
this.drainHeadTo__(temp);
list.addAll(index, temp);
return true;
}
/**
* "Drain" all the current items from the deque's tail into specified list
* at the specified index.
* Return whether the deque changed as a result.
*/
public boolean drainTailTo(List<? super E> list, int index) {
synchronized (this.mutex) {
return this.drainTailTo_(list, index);
}
}
/**
* Pre-condition: synchronized
*/
private boolean drainTailTo_(List<? super E> list, int index) {
if (this.deque.isEmpty()) {
return false;
}
if (index == list.size()) {
return this.drainTailTo__(list);
}
ArrayList<E> temp = new ArrayList<E>();
this.drainTailTo__(temp);
list.addAll(index, temp);
return true;
}
/**
* "Drain" all the current items from the deque's head into specified stack.
* Return whether the deque changed as a result.
*/
public boolean drainHeadTo(Stack<? super E> stack) {
synchronized (this.mutex) {
return this.drainHeadTo_(stack);
}
}
/**
* Pre-condition: synchronized
*/
private boolean drainHeadTo_(Stack<? super E> stack) {
if (this.deque.isEmpty()) {
return false;
}
do {
stack.push(this.deque.dequeueHead());
} while ( ! this.deque.isEmpty());
this.mutex.notifyAll();
return true;
}
/**
* "Drain" all the current items from the deque's tail into specified stack.
* Return whether the deque changed as a result.
*/
public boolean drainTailTo(Stack<? super E> stack) {
synchronized (this.mutex) {
return this.drainTailTo_(stack);
}
}
/**
* Pre-condition: synchronized
*/
private boolean drainTailTo_(Stack<? super E> stack) {
if (this.deque.isEmpty()) {
return false;
}
do {
stack.push(this.deque.dequeueTail());
} while ( ! this.deque.isEmpty());
this.mutex.notifyAll();
return true;
}
/**
* "Drain" all the current items from the deque's head into specified deque's tail.
* Return whether the deque changed as a result.
* @see #enqueueTailAll(Deque)
*/
public boolean drainHeadTo(Deque<? super E> q) {
synchronized (this.mutex) {
return this.drainHeadTo_(q);
}
}
/**
* Pre-condition: synchronized
*/
private boolean drainHeadTo_(Deque<? super E> q) {
if (this.deque.isEmpty()) {
return false;
}
do {
q.enqueueTail(this.deque.dequeueHead());
} while ( ! this.deque.isEmpty());
this.mutex.notifyAll();
return true;
}
/**
* "Drain" all the current items from the deque's tail into specified deque's head.
* Return whether the deque changed as a result.
* @see #enqueueTailAll(Deque)
*/
public boolean drainTailTo(Deque<? super E> q) {
synchronized (this.mutex) {
return this.drainTailTo_(q);
}
}
/**
* Pre-condition: synchronized
*/
private boolean drainTailTo_(Deque<? super E> q) {
if (this.deque.isEmpty()) {
return false;
}
do {
q.enqueueHead(this.deque.dequeueTail());
} while ( ! this.deque.isEmpty());
this.mutex.notifyAll();
return true;
}
/**
* "Drain" all the current items from the deque's head
* and add them on the specified map, using the specified key transformer
* to generate the key for each item.
* Return whether the deque changed as a result.
*/
public <K> boolean drainHeadTo(Map<K, ? super E> map, Transformer<? super E, ? extends K> keyTransformer) {
synchronized (this.mutex) {
return this.drainHeadTo_(map, keyTransformer);
}
}
/**
* Pre-condition: synchronized
*/
private <K> boolean drainHeadTo_(Map<K, ? super E> map, Transformer<? super E, ? extends K> keyTransformer) {
if (this.deque.isEmpty()) {
return false;
}
do {
MapTools.add(map, this.deque.dequeueHead(), keyTransformer);
} while ( ! this.deque.isEmpty());
this.mutex.notifyAll();
return true;
}
/**
* "Drain" all the current items from the deque's tail
* and add them on the specified map, using the specified key transformer
* to generate the key for each item.
* Return whether the deque changed as a result.
*/
public <K> boolean drainTailTo(Map<K, ? super E> map, Transformer<? super E, ? extends K> keyTransformer) {
synchronized (this.mutex) {
return this.drainTailTo_(map, keyTransformer);
}
}
/**
* Pre-condition: synchronized
*/
private <K> boolean drainTailTo_(Map<K, ? super E> map, Transformer<? super E, ? extends K> keyTransformer) {
if (this.deque.isEmpty()) {
return false;
}
do {
MapTools.add(map, this.deque.dequeueTail(), keyTransformer);
} while ( ! this.deque.isEmpty());
this.mutex.notifyAll();
return true;
}
/**
* "Drain" all the current items from the deque's head
* and add them on the specified map, using the specified key transformer
* to generate the key for each dequeued item and the specified value transformer
* to generator the value for each dequeued item.
* Return whether the deque changed as a result.
*/
public <K, V> boolean drainHeadTo(Map<K, V> map, Transformer<? super E, ? extends K> keyTransformer, Transformer<? super E, ? extends V> valueTransformer) {
synchronized (this.mutex) {
return this.drainHeadTo_(map, keyTransformer, valueTransformer);
}
}
/**
* Pre-condition: synchronized
*/
private <K, V> boolean drainHeadTo_(Map<K, V> map, Transformer<? super E, ? extends K> keyTransformer, Transformer<? super E, ? extends V> valueTransformer) {
if (this.deque.isEmpty()) {
return false;
}
do {
MapTools.add(map, this.deque.dequeueHead(), keyTransformer, valueTransformer);
} while ( ! this.deque.isEmpty());
this.mutex.notifyAll();
return true;
}
/**
* "Drain" all the current items from the deque's tail
* and add them on the specified map, using the specified key transformer
* to generate the key for each dequeued item and the specified value transformer
* to generator the value for each dequeued item.
* Return whether the deque changed as a result.
*/
public <K, V> boolean drainTailTo(Map<K, V> map, Transformer<? super E, ? extends K> keyTransformer, Transformer<? super E, ? extends V> valueTransformer) {
synchronized (this.mutex) {
return this.drainTailTo_(map, keyTransformer, valueTransformer);
}
}
/**
* Pre-condition: synchronized
*/
private <K, V> boolean drainTailTo_(Map<K, V> map, Transformer<? super E, ? extends K> keyTransformer, Transformer<? super E, ? extends V> valueTransformer) {
if (this.deque.isEmpty()) {
return false;
}
do {
MapTools.add(map, this.deque.dequeueTail(), keyTransformer, valueTransformer);
} while ( ! this.deque.isEmpty());
this.mutex.notifyAll();
return true;
}
/**
* Return the object the deque locks on while performing
* its operations.
*/
public Object getMutex() {
return this.mutex;
}
// ********** standard methods **********
@Override
public String toString() {
synchronized (this.mutex) {
return this.deque.toString();
}
}
private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
synchronized (this.mutex) {
s.defaultWriteObject();
}
}
}