001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.collections4.queue;
018
019import java.util.Queue;
020
021import org.apache.commons.collections4.collection.SynchronizedCollection;
022
023/**
024 * Decorates another {@link Queue} to synchronize its behaviour for a multi-threaded environment.
025 * <p>
026 * Methods are synchronized, then forwarded to the decorated queue. Iterators must be separately synchronized around the
027 * loop.
028 * </p>
029 *
030 * @param <E> the type of the elements in the collection
031 * @since 4.2
032 */
033public class SynchronizedQueue<E> extends SynchronizedCollection<E> implements Queue<E> {
034
035    /** Serialization version */
036    private static final long serialVersionUID = 1L;
037
038    /**
039     * Factory method to create a synchronized queue.
040     *
041     * @param <E>
042     *            the type of the elements in the queue
043     * @param queue
044     *            the queue to decorate, must not be null
045     * @return a new synchronized Queue
046     * @throws NullPointerException
047     *             if queue is null
048     */
049    public static <E> SynchronizedQueue<E> synchronizedQueue(final Queue<E> queue) {
050        return new SynchronizedQueue<>(queue);
051    }
052
053    // -----------------------------------------------------------------------
054    /**
055     * Constructor that wraps (not copies).
056     *
057     * @param queue
058     *            the queue to decorate, must not be null
059     * @throws NullPointerException
060     *             if queue is null
061     */
062    protected SynchronizedQueue(final Queue<E> queue) {
063        super(queue);
064    }
065
066    /**
067     * Constructor that wraps (not copies).
068     *
069     * @param queue
070     *            the queue to decorate, must not be null
071     * @param lock
072     *            the lock to use, must not be null
073     * @throws NullPointerException
074     *             if queue or lock is null
075     */
076    protected SynchronizedQueue(final Queue<E> queue, final Object lock) {
077        super(queue, lock);
078    }
079
080    /**
081     * Gets the queue being decorated.
082     *
083     * @return the decorated queue
084     */
085    @Override
086    protected Queue<E> decorated() {
087        return (Queue<E>) super.decorated();
088    }
089
090    @Override
091    public E element() {
092        synchronized (lock) {
093            return decorated().element();
094        }
095    }
096
097    @Override
098    public boolean equals(final Object object) {
099        if (object == this) {
100            return true;
101        }
102        synchronized (lock) {
103            return decorated().equals(object);
104        }
105    }
106
107    // -----------------------------------------------------------------------
108
109    @Override
110    public int hashCode() {
111        synchronized (lock) {
112            return decorated().hashCode();
113        }
114    }
115
116    @Override
117    public boolean offer(final E e) {
118        synchronized (lock) {
119            return decorated().offer(e);
120        }
121    }
122
123    @Override
124    public E peek() {
125        synchronized (lock) {
126            return decorated().peek();
127        }
128    }
129
130    @Override
131    public E poll() {
132        synchronized (lock) {
133            return decorated().poll();
134        }
135    }
136
137    @Override
138    public E remove() {
139        synchronized (lock) {
140            return decorated().remove();
141        }
142    }
143
144}