org.glassfish.grizzly.connectionpool.Chain Maven / Gradle / Ivy
/*
* Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
package org.glassfish.grizzly.connectionpool;
import java.util.LinkedList;
/**
* Minimalistic linked list implementation. This implementation doesn't work directly with objects, but their
* {@link Link}s, so there is no performance penalty for locating object in the list.
*
* The Chain implementation is not thread safe.
*
* @author Alexey Stashok
*/
final class Chain {
/**
* The size of the chain (number of elements stored).
*/
private int size;
/**
* The first link in the chain
*/
private Link firstLink;
/**
* The last link in the chain
*/
private Link lastLink;
/**
* Returns true if this Chain doesn't have any element stored, or false otherwise.
*/
public boolean isEmpty() {
return size == 0;
}
/**
* Returns the number of elements stored in this Chain.
*/
public int size() {
return size;
}
/**
* Returns the first {@link Link} in this Chain.
*/
public Link getFirstLink() {
return firstLink;
}
/**
* Returns the last {@link Link} in this Chain.
*/
public Link getLastLink() {
return lastLink;
}
/**
* Adds a {@link Link} to the beginning of this Chain.
*/
public void offerFirst(final Link link) {
if (link.isAttached()) {
throw new IllegalStateException("Already linked");
}
link.next = firstLink;
if (firstLink != null) {
firstLink.prev = link;
}
firstLink = link;
if (lastLink == null) {
lastLink = firstLink;
}
link.attach();
size++;
}
/**
* Adds a {@link Link} to the end of this Chain.
*/
public void offerLast(final Link link) {
if (link.isAttached()) {
throw new IllegalStateException("Already linked");
}
link.prev = lastLink;
if (lastLink != null) {
lastLink.next = link;
}
lastLink = link;
if (firstLink == null) {
firstLink = lastLink;
}
link.attach();
size++;
}
/**
* Removes and returns the last {@link Link} of this Chain.
*/
public Link pollLast() {
if (lastLink == null) {
return null;
}
final Link link = lastLink;
lastLink = link.prev;
if (lastLink == null) {
firstLink = null;
} else {
lastLink.next = null;
}
link.detach();
size--;
return link;
}
/**
* Removes and returns the first {@link Link} of this Chain.
*/
public Link pollFirst() {
if (firstLink == null) {
return null;
}
final Link link = firstLink;
firstLink = link.next;
if (firstLink == null) {
lastLink = null;
} else {
firstLink.prev = null;
}
link.detach();
size--;
return link;
}
/**
* Removes the {@link Link} from this Chain. Unlike {@link LinkedList#remove(java.lang.Object)}, this operation
* is cheap, because the {@link Link} already has information about its location in the Chain, so no additional
* lookup needed.
*
* @param link the {@link Link} to be removed.
*/
public boolean remove(final Link link) {
if (!link.isAttached()) {
return false;
}
final Link prev = link.prev;
final Link next = link.next;
if (prev != null) {
prev.next = next;
}
if (next != null) {
next.prev = prev;
}
link.detach();
if (lastLink == link) {
lastLink = prev;
if (lastLink == null) {
firstLink = null;
}
} else if (firstLink == link) {
firstLink = next;
}
size--;
return true;
}
/**
* Moves the {@link Link} towards the Chain's head by 1 element. If the {@link Link} is already located at the
* Chain's head - the method invocation will not have any effect.
*
* @param link the {@link Link} to be moved.
*/
public void moveTowardsHead(final Link link) {
final Link prev = link.prev;
// check if this is head
if (prev == null) {
return;
}
final Link next = link.next;
final Link prevPrev = prev.prev;
if (prevPrev != null) {
prevPrev.next = link;
}
link.prev = prevPrev;
link.next = prev;
prev.prev = link;
prev.next = next;
if (next != null) {
next.prev = prev;
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy