All Downloads are FREE. Search and download functionalities are using the official Maven repository.

craterdog.collections.Queue Maven / Gradle / Ivy

/************************************************************************
 * Copyright (c) Crater Dog Technologies(TM).  All Rights Reserved.     *
 ************************************************************************
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.        *
 *                                                                      *
 * This code is free software; you can redistribute it and/or modify it *
 * under the terms of The MIT License (MIT), as published by the Open   *
 * Source Initiative. (See http://opensource.org/licenses/MIT)          *
 ************************************************************************/
package craterdog.collections;

import com.fasterxml.jackson.annotation.JsonValue;
import craterdog.collections.abstractions.ClosedCollection;
import org.slf4j.ext.XLogger;
import org.slf4j.ext.XLoggerFactory;


/**
 * This collection class implements a queue (FIFO) data structure.  Normally, multiple
 * threads will be accessing a queue at the same time.  This class enforces synchronized
 * access to all methods of this class.  The implementation dynamically scales up and down
 * the size of the underlying data structures as the number elements changes over time.
 *
 * @author Derk Norton
 * @param  The type of element managed by this collection.
 */
public class Queue extends ClosedCollection {

    static private final XLogger logger = XLoggerFactory.getXLogger(Queue.class);

    private final int capacity;


    /**
     * This constructor creates a new queue of unlimited capacity.
     */
    public Queue() {
        logger.entry();
        this.capacity = Integer.MAX_VALUE;
        logger.exit();
    }


    /**
     * This constructor creates a new queue with the specified capacity.
     *
     * @param capacity The maximum number of elements that can be in the queue
     * at one time.
     */
    public Queue(int capacity) {
        logger.entry(capacity);
        this.capacity = capacity;
        logger.exit();
    }


    @JsonValue
    @Override
    public E[] toArray() {
        return super.toArray();
    }


    /**
     * This method adds a new element to the tail of the queue.  If the queue
     * is currently at capacity this method will block until the capacity
     * drops.
     *
     * @param element The new element to be added.
     * @throws java.lang.InterruptedException The thread that was waiting to add an element
     * was interrupted.
     */
    public final synchronized void addElement(E element) throws InterruptedException {
        logger.entry();
        while (true) {  // do this in a loop in case there are spurious wakeups (see Object.wait() javadoc)
            int size = list.size();
            if (size < capacity) {
                logger.debug("Adding the element: " + element);
                list.add(element);
                notify();  // waiting removeElement() calls
                break;
            } else {
                logger.debug("Waiting for the queue to drop from maximum capacity...");
                wait();  // for a removeElement() call
            }
        }
        logger.exit();
    }


    /**
     * This method removes the next element from the head of the queue.  If
     * the queue is empty, the method blocks until an element is available.
     *
     * @return The head element in the queue.
     * @throws java.lang.InterruptedException The thread that was waiting to remove an element
     * was interrupted.
     */
    public final synchronized E removeElement() throws InterruptedException {
        logger.entry();
        E element = null;
        while (true) {  // do this in a loop in case there are spurious wakeups (see Object.wait() javadoc)
            int size = list.size();
            if (size > 0) {
                element = list.remove(0);  // zero based indexing
                logger.debug("Removed the element: " + element);
                notify();  // waiting addElement() calls
                break;
            } else {
                logger.debug("Waiting for an element to be added to the empty queue...");
                wait();  // for an addElement() call
            }
        }
        logger.exit(element);
        return element;
    }


    /**
     * This method returns a reference to the element at the head of the queue
     * without removing the element from the queue.
     *
     * @return The head element in the queue, or null if the queue is empty.
     */
    public final synchronized E getHead() {
        logger.entry();
        E element = null;
        int size = list.size();
        if (size > 0) {
            element = list.get(0);  // zero based indexing
        }
        logger.exit();
        return element;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy