blob: 386d30374e7ad73ecd93815c7c56f917507d23a9 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package com.datatorrent.lib.appdata.query;
import com.google.common.base.Preconditions;
/**
* This is a doubly linked list to be used for queueing queries.
* @param <T> The type of the data used for queueing
* @since 3.0.0
*/
public class QueueList<T>
{
/**
* The number of nodes in the {@link QueueList}.
*/
private int size = 0;
/**
* The head of the queue.
*/
private QueueListNode<T> head;
/**
* The tail of the queue.
*/
private QueueListNode<T> tail;
/**
* A lock which is used to make queueing and dequeueing from this {@link QueueList} thread safe.
*/
private final Object lock = new Object();
/**
* Create a queue list.
*/
public QueueList()
{
//Do nothing
}
/**
* Enqueues the given node to the list.
* @param node The node to enqueue in the list.
*/
public void enqueue(QueueListNode<T> node)
{
synchronized (lock) {
Preconditions.checkNotNull(node);
size++;
if (head == null) {
head = node;
tail = node;
node.setNext(null);
node.setPrev(null);
return;
}
tail.setNext(node);
node.setPrev(tail);
node.setNext(null);
tail = node;
}
}
/**
* Returns the head of the QueueList.
* @return The head node of the queue list.
*/
public QueueListNode<T> getHead()
{
synchronized (lock) {
return head;
}
}
/**
* Removes the given node from the QueueList.
* @param node The node to remove from this QueueList.
*/
public void removeNode(QueueListNode<T> node)
{
synchronized (lock) {
size--;
//Handle the case when adding to the end of list and
//removing a node in parallel
if (head == node) {
if (tail == node) {
head = null;
tail = null;
} else {
head = node.getNext();
head.setPrev(null);
}
} else {
if (tail == node) {
tail = node.getPrev();
tail.setNext(null);
} else {
node.getPrev().setNext(node.getNext());
node.getNext().setPrev(node.getPrev());
}
}
}
}
/**
* Returns the size of the {@link QueueList}.
* @return The size of the {@link QueueList}.
*/
public int getSize()
{
return size;
}
/**
* This class represents a node in the QueueList, and holds a data payload provided by the user of type T.
* @param <T> The type of the data payload of the node.
*/
public static class QueueListNode<T>
{
private QueueListNode<T> prev;
private QueueListNode<T> next;
private T payload;
/**
* Creates a new queue list node with node data payload.
*/
public QueueListNode()
{
}
/**
* Creates a new queue list node with the given data payload.
* @param payload The data payload for this node.
*/
public QueueListNode(T payload)
{
this.payload = payload;
}
/**
* Gets the previous node that this node points to.
* @return The previous node that this node points to.
*/
public QueueListNode<T> getPrev()
{
return prev;
}
/**
* Sets the previous node that this node points to.
* @param prev The previous node that this node will point to.
*/
public void setPrev(QueueListNode<T> prev)
{
this.prev = prev;
}
/**
* Gets the next element this node points to.
* @return The next element this node points to.
*/
public QueueListNode<T> getNext()
{
return next;
}
/**
* Sets the next element this node points to.
* @param next The next element this node points to.
*/
public void setNext(QueueListNode<T> next)
{
this.next = next;
}
/**
* Gets the data payload for the node.
* @return The data payload for the node.
*/
public T getPayload()
{
return payload;
}
/**
* Sets the data payload for the node.
* @param payload The data payload for the node.
*/
public void setPayload(T payload)
{
this.payload = payload;
}
@Override
public String toString()
{
return "QueueListNode{" + "payload=" + payload + '}';
}
}
}