diff --git a/pp.A4-HandOverHandLocking/src/main/java/pp/ThreadsafeSimplifiedList.java b/pp.A4-HandOverHandLocking/src/main/java/pp/ThreadsafeSimplifiedList.java index a6e5f71..f9bb9dc 100644 --- a/pp.A4-HandOverHandLocking/src/main/java/pp/ThreadsafeSimplifiedList.java +++ b/pp.A4-HandOverHandLocking/src/main/java/pp/ThreadsafeSimplifiedList.java @@ -3,137 +3,121 @@ package pp; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; -import net.jcip.annotations.ThreadSafe; +public class ThreadsafeSimplifiedList + implements SimplifiedList { -@ThreadSafe -public class ThreadsafeSimplifiedList implements SimplifiedList { - private Node first; - private final Lock listLock = new ReentrantLock(); + private Node head; + private final Lock listLock = new ReentrantLock(); - private class Node { - private U element; - private Node prev; - private Node next; - private final Lock lock = new ReentrantLock(); + private class Node { + private U element; + private Node next; + private final Lock nodeLock; - private Node(U element, Node prev, Node next) { - super(); - this.element = element; - this.prev = prev; - this.next = next; - } - } + private Node(U element, Node prev, Node next) { + super(); + this.element = element; + this.next = next; + this.nodeLock = new ReentrantLock(); + } + } - public ThreadsafeSimplifiedList() { - super(); - this.first = null; - } + /** + * Returns the element at the specified position in this list. + * + * @param index index of the element to return + * @return the element at the specified position in this list + */ + @Override + public T get(int index) { + this.listLock.lock(); + var ptr = this.head; + ptr.nodeLock.lock(); + this.listLock.unlock(); + for (var i = 0; i < index; i++) { + if (ptr.next != null) { + ptr.next.nodeLock.lock(); + var savePtr = ptr; + ptr = ptr.next; + savePtr.nodeLock.unlock(); + } else { + throw new IndexOutOfBoundsException(index + " out of bounds"); + } + } + + try {return delay(ptr.element);} + finally { ptr.nodeLock.unlock();} + } - /** - * Returns the element at the specified position in this list. - * - * @param index index of the element to return - * @return the element at the specified position in this list - */ - @Override - public T get(int index) { - this.listLock.lock(); - var ptr = this.first; - ptr.lock.lock(); - this.listLock.unlock(); - for (var j = 0; j < index; j++) { - if (ptr.next != null) { - ptr.next.lock.lock(); - var savePtr = ptr; - ptr = ptr.next; - savePtr.lock.unlock(); - } else { - throw new IndexOutOfBoundsException(index + " out of bounds"); - } - } - try { - return delay(ptr.element); - } finally { - ptr.lock.unlock(); - } - } + /** + * Appends the specified element to the end of this list. There are no + * limitations on what elements may be added to this list. + * + * @param element element to be appended to this list + * @return true + * @see java.util.Collection#add(Object) + * + */ + @Override + public boolean add(T element) { + this.listLock.lock(); + if (this.head != null) { + var ptr = this.head; + ptr.nodeLock.lock(); + this.listLock.unlock(); + while (ptr.next != null) { + ptr.next.nodeLock.lock(); + var savePtr = ptr; + ptr = ptr.next; + savePtr.nodeLock.unlock(); + } + ptr.next = new Node<>(element, ptr, null); + ptr.nodeLock.unlock(); + } else { + this.head = new Node<>(element, null, null); + this.listLock.unlock(); + } + return true; + } - /** - * Appends the specified element to the end of this list. There are no - * limitations on what elements may be added to this list. - * - * @param element element to be appended to this list - * @return true - * @see java.util.Collection#add(Object) - * - */ - @Override - public boolean add(T element) { - this.listLock.lock(); - if (this.first != null) { - var ptr = this.first; - ptr.lock.lock(); - this.listLock.unlock(); - while (ptr.next != null) { - ptr.next.lock.lock(); - var saveNode = ptr; - ptr = ptr.next; - saveNode.lock.unlock(); - } - ptr.next = new Node<>(element, ptr, null); - } else { - this.first = new Node<>(element, null, null); - this.listLock.unlock(); - } - return true; - } + /** + * Replaces the element at the specified position in this list with the + * specified element. + * + * @param index index of the element to replace + * @param element element to be stored at the specified position + * @return the element previously at the specified position + */ + @Override + public T set(int index, T element) { + this.listLock.lock(); + var ptr = this.head; + ptr.nodeLock.lock(); + this.listLock.unlock(); + for (var i = 0; i < index; i++) { + if (ptr.next != null) { + ptr.next.nodeLock.lock(); + var savePtr = ptr; + ptr = ptr.next; + savePtr.nodeLock.unlock(); + } else + throw new IndexOutOfBoundsException(index + " out of bounds"); + + } + ptr.element = element; + ptr.nodeLock.unlock(); + return element; + } - /** - * Replaces the element at the specified position in this list with the - * specified element. - * - * @param index index of the element to replace - * @param element element to be stored at the specified position - * @return the element previously at the specified position - */ - @Override - public T set(int index, T element) { - this.listLock.lock(); - var ptr = this.first; - ptr.lock.lock(); - this.listLock.unlock(); - for (var j = 0; j < index; j++) { - if (ptr.next != null) { - ptr.next.lock.lock(); - var saveNode = ptr; - ptr = ptr.next; - saveNode.lock.unlock(); - } else { - throw new IndexOutOfBoundsException(index + " out of bounds"); - } - } - try { - var prevElement = ptr.element; - ptr.element = element; - return prevElement; - } finally { - ptr.lock.unlock(); - } - } - - /** - * Returns true if this list contains no elements. - * - * @return true if this list contains no elements - */ - @Override - public boolean isEmpty() { - this.listLock.lock(); - try { - return this.first == null; - } finally { - this.listLock.unlock(); - } - } + /** + * Returns true if this list contains no elements. + * + * @return true if this list contains no elements + */ + @Override + public boolean isEmpty() { + this.listLock.lock(); + try { return this.head == null; } + finally { this.listLock.unlock();} + } } -