/* * MicroJIAC - A Lightweight Agent Framework * This file is part of MicroJIAC Base-Implementation. * * Copyright (c) 2007-2012 DAI-Labor, Technische Universität Berlin * * This library includes software developed at DAI-Labor, Technische * Universität Berlin (http://www.dai-labor.de) * * This library is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library. If not, see <http://www.gnu.org/licenses/>. */ /* * $Id$ */ package de.jiac.micro.util; import java.util.NoSuchElementException; import de.jiac.micro.core.scope.Scope; /** * @author Erdene-Ochir Tuguldur * @author Marcel Patzlaff * @version $Revision$ */ public class List { public static class Node { Object _value; Node _next; Node _previous; public final Node next() { return _next; } public final Node previous() { return _previous; } public final Object value() { return _value; } } private final class CapacityIncreaser implements Runnable { CapacityIncreaser() {} public synchronized void run() { if(_emptyNodes.next() != null || _emptyNodes.previous() != null) { return; } Node node= _emptyNodes; for(int i= 0; i < 4; ++i) { node._next= newNode(); node._next._previous= node; node= node._next; } } } private static volatile int ONE= 1; private final transient Node _head; private final transient Node _tail; private final transient Node _emptyNodes; private volatile transient int _size; private final transient CapacityIncreaser _capacityIncreaser; public List() { _head= newNode(); _tail= newNode(); _emptyNodes= newNode(); _head._next= _tail; _tail._previous= _head; _size= 0; _capacityIncreaser= new CapacityIncreaser(); } public final synchronized Node addFirst(Object obj) { if(_emptyNodes._next == null) { Scope.executeInScope(_capacityIncreaser); } // get new node final Node newNode= _emptyNodes._next; _emptyNodes._next= newNode._next; // add node behind head final Node next= _head._next; newNode._next= next; next._previous= newNode; _head._next= newNode; newNode._previous= _head; newNode._value= obj; _size+= ONE; return newNode; } public final synchronized Node addLast(Object obj) { if(_emptyNodes._next == null) { Scope.executeInScope(_capacityIncreaser); } // get new node final Node newNode= _emptyNodes._next; _emptyNodes._next= newNode._next; // add node before tail final Node previous= _tail._previous; newNode._previous= previous; previous._next= newNode; _tail._previous= newNode; newNode._next= _tail; newNode._value= obj; _size+= ONE; return newNode; } public final synchronized boolean contains(Object obj) { return search(obj) != null; } public final synchronized Node get(int index) { if(_size <= index || index < 0) { throw new NoSuchElementException("index out of bounds: " + index); } Node node; if(_size >> 1 > index) { // from head node= _head; for(int i= index; i >= 0; --i) { node= node._next; } } else { // from tail node= _tail; for(int i= index; i >= 0; --i) { node= node._previous; } } return node; } public final synchronized Object removeFirst() { if(_head._next == _tail) { return null; } final Node first= _head._next; final Object val= first._value; delete(first); return val; } public final synchronized Object removeLast() { if(_tail._previous == _head) { return null; } final Node last= _tail._previous; final Object val= last._value; delete(last); return val; } public final synchronized boolean remove(Object obj) { Node node= search(obj); if(node != null) { delete(node); return true; } return false; } public final synchronized void clear() { for(Node node; (node= _head._next) != _tail; ) { // for(Node node= _head; (node= node._next) != _tail; ) { delete(node); } } public final Node head() { return _head; } public final Node tail() { return _tail; } public final int size() { return _size; } protected Node newNode() { return new Node(); } public synchronized final Node search(Object value) { for(Node node= _head; (node= node._next) != _tail; ) { if(value == null ? node._value == null : (value == node._value || value.equals(node._value))) { return node; } } return null; } public synchronized final void delete(Node node) { if(_emptyNodes._previous != null) { _emptyNodes._previous._previous= null; _emptyNodes._previous._next= _emptyNodes._next; _emptyNodes._next= _emptyNodes._previous; _emptyNodes._previous= null; } _size-= ONE; node._value= null; // remove from list node._next._previous= node._previous; node._previous._next= node._next; // save the old neighbour pointers to support iteration _emptyNodes._previous= node; node._next= _tail._next; node._previous= _tail; _tail._next= node; } }