diff --git a/classpath/java/lang/Thread.java b/classpath/java/lang/Thread.java index 095691d342..5d99c2f092 100644 --- a/classpath/java/lang/Thread.java +++ b/classpath/java/lang/Thread.java @@ -14,6 +14,9 @@ import java.util.Map; import java.util.WeakHashMap; public class Thread implements Runnable { + // set and accessed from within LockSupport + protected volatile Object parkBlocker; + private long peer; private volatile boolean interrupted; private volatile boolean unparked; diff --git a/classpath/java/util/Deque.java b/classpath/java/util/Deque.java new file mode 100644 index 0000000000..2739965411 --- /dev/null +++ b/classpath/java/util/Deque.java @@ -0,0 +1,31 @@ +/* Copyright (c) 2008-2014, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public interface Deque extends Queue { + public boolean offerFirst(T e); + public void push(T e); + public void addFirst(T element); + public boolean offerLast(T e); + public void addLast(T element); + public T peekFirst(); + public T getFirst(); + public T peekLast(); + public T getLast(); + public T pollFirst(); + public T removeFirst(); + public T pop(); + public T pollLast(); + public T removeLast(); + public Iterator descendingIterator(); + public boolean removeLastOccurrence(Object o); + public boolean removeFirstOccurrence(Object o); +} diff --git a/classpath/java/util/LinkedList.java b/classpath/java/util/LinkedList.java index e161a7714e..d42c6961b2 100644 --- a/classpath/java/util/LinkedList.java +++ b/classpath/java/util/LinkedList.java @@ -10,7 +10,7 @@ package java.util; -public class LinkedList extends AbstractSequentialList { +public class LinkedList extends AbstractSequentialList implements Deque { private Cell front; private Cell rear; private int size; @@ -85,14 +85,17 @@ public class LinkedList extends AbstractSequentialList { } } + @Override public int size() { return size; } + @Override public boolean contains(Object element) { return find(element) != null; } + @Override public int indexOf(Object element) { int i = 0; for (Cell c = front; c != null; c = c.next) { @@ -104,6 +107,7 @@ public class LinkedList extends AbstractSequentialList { return -1; } + @Override public int lastIndexOf(Object element) { int i = size; for (Cell c = rear; c != null; c = c.prev) { @@ -115,16 +119,24 @@ public class LinkedList extends AbstractSequentialList { return -1; } + @Override + public boolean offer(T element) { + return add(element); + } + + @Override public boolean add(T element) { addLast(element); return true; } + @Override public boolean addAll(Collection collection) { for (T t: collection) add(t); return true; } + @Override public void add(int index, T element) { if (index == 0) { addFirst(element); @@ -135,10 +147,31 @@ public class LinkedList extends AbstractSequentialList { } } + @Override + public boolean offerFirst(T e) { + addFirst(e); + + return true; + } + + @Override + public void push(T e) { + addFirst(e); + } + + @Override public void addFirst(T element) { addFirst(new Cell(element, null, null)); } + @Override + public boolean offerLast(T e) { + addLast(e); + + return true; + } + + @Override public void addLast(T element) { addLast(new Cell(element, null, null)); } @@ -147,6 +180,7 @@ public class LinkedList extends AbstractSequentialList { return find(index).value; } + @Override public T set(int index, T value) { Cell c = find(index); T old = c.value; @@ -154,6 +188,21 @@ public class LinkedList extends AbstractSequentialList { return old; } + @Override + public T peek() { + return peekFirst(); + } + + @Override + public T peekFirst() { + if (front != null) { + return front.value; + } else { + return null; + } + } + + @Override public T getFirst() { if (front != null) { return front.value; @@ -161,7 +210,17 @@ public class LinkedList extends AbstractSequentialList { throw new NoSuchElementException(); } } + + @Override + public T peekLast() { + if (rear != null) { + return rear.value; + } else { + return null; + } + } + @Override public T getLast() { if (rear != null) { return rear.value; @@ -170,27 +229,57 @@ public class LinkedList extends AbstractSequentialList { } } + @Override public T remove(int index) { Cell c = find(index); remove(c); return c.value; } + @Override public boolean isEmpty() { return size() == 0; } - public T removeFirst() { + @Override + public T poll() { + return pollFirst(); + } + + @Override + public T pollFirst() { if (front != null) { T v = front.value; remove(front); return v; } else { - throw new NoSuchElementException(); + return null; } } - public T removeLast() { + @Override + public T removeFirst() { + T result = pollFirst(); + + if (result == null) { + throw new NoSuchElementException(); + } else { + return result; + } + } + + @Override + public T pop() { + return removeFirst(); + } + + @Override + public T remove() { + return removeFirst(); + } + + @Override + public T pollLast() { if (rear != null) { T v = rear.value; remove(rear); @@ -200,6 +289,18 @@ public class LinkedList extends AbstractSequentialList { } } + @Override + public T removeLast() { + T result = pollLast(); + + if (result == null) { + throw new NoSuchElementException(); + } else { + return result; + } + } + + @Override public boolean remove(Object element) { Cell c = find(element); if (c == null) { @@ -210,15 +311,23 @@ public class LinkedList extends AbstractSequentialList { } } + @Override public void clear() { front = rear = null; size = 0; } + @Override public Iterator iterator() { return listIterator(); } + @Override + public ListIterator listIterator() { + return listIterator(0); + } + + @Override public ListIterator listIterator(int index) { MyIterator it = new MyIterator(); for (int i = 0; i < index; ++i) { @@ -227,14 +336,67 @@ public class LinkedList extends AbstractSequentialList { return it; } - public ListIterator listIterator() { - return listIterator(0); + @Override + public Iterator descendingIterator() { + final ListIterator li = listIterator(size()); + + return new Iterator() { + @Override + public T next() { + return li.previous(); + } + + @Override + public boolean hasNext() { + return li.hasPrevious(); + } + + @Override + public void remove() { + li.remove(); + } + }; } + @Override public String toString() { return Collections.toString(this); } + @Override + public T element() { + T result = peek(); + if (result == null) { + throw new NoSuchElementException(); + } else { + return result; + } + } + + @Override + public boolean removeFirstOccurrence(Object o) { + int index = indexOf(o); + if (index > 0) { + remove(index); + + return true; + } else { + return false; + } + } + + @Override + public boolean removeLastOccurrence(Object o) { + int lastIndex = lastIndexOf(o); + if (lastIndex > 0) { + remove(lastIndex); + + return true; + } else { + return false; + } + } + private static class Cell { public T value; public Cell prev; diff --git a/classpath/java/util/concurrent/ConcurrentLinkedQueue.java b/classpath/java/util/concurrent/ConcurrentLinkedQueue.java index 93105317f2..357f8a7ded 100644 --- a/classpath/java/util/concurrent/ConcurrentLinkedQueue.java +++ b/classpath/java/util/concurrent/ConcurrentLinkedQueue.java @@ -1,8 +1,13 @@ package java.util.concurrent; +import java.util.Collection; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.Queue; + import avian.Atomic; -public class ConcurrentLinkedQueue { +public class ConcurrentLinkedQueue implements Queue { private static final long QueueHead; private static final long QueueTail; private static final long NodeNext; @@ -25,11 +30,20 @@ public class ConcurrentLinkedQueue { private volatile Node head = new Node(null, null); private volatile Node tail = head; + @Override public void clear() { - // todo: can we safely make this O(1)? + // TODO - can we safely make this O(1)? while (poll() != null) { } } + @Override + public boolean offer(T element) { + add(element); + + return true; + } + + @Override public boolean add(T value) { Node n = new Node(value, null); while (true) { @@ -48,14 +62,36 @@ public class ConcurrentLinkedQueue { return true; } + @Override public T peek() { return poll(false); } + @Override + public T element() { + T result = peek(); + if (result == null) { + throw new NoSuchElementException(); + } else { + return result; + } + } + + @Override public T poll() { return poll(true); } + @Override + public T remove() { + T result = poll(); + if (result == null) { + throw new NoSuchElementException(); + } else { + return result; + } + } + private T poll(boolean remove) { while (true) { Node h = head; @@ -90,4 +126,63 @@ public class ConcurrentLinkedQueue { this.next = next; } } + + @Override + public int size() { + // TODO - implement + throw new UnsupportedOperationException(); + } + + @Override + public boolean isEmpty() { + return size() == 0; + } + + @Override + public boolean contains(Object element) { + // TODO - implement + throw new UnsupportedOperationException(); + } + + @Override + public boolean containsAll(Collection c) { + // TODO - implement + throw new UnsupportedOperationException(); + } + + @Override + public boolean addAll(Collection collection) { + // TODO - implement + throw new UnsupportedOperationException(); + } + + @Override + public boolean remove(Object element) { + // TODO - implement + throw new UnsupportedOperationException(); + } + + @Override + public boolean removeAll(Collection c) { + // TODO - implement + throw new UnsupportedOperationException(); + } + + @Override + public Object[] toArray() { + // TODO - implement + throw new UnsupportedOperationException(); + } + + @Override + public S[] toArray(S[] array) { + // TODO - implement + throw new UnsupportedOperationException(); + } + + @Override + public Iterator iterator() { + // TODO - implement + throw new UnsupportedOperationException(); + } } diff --git a/classpath/java/util/concurrent/locks/Condition.java b/classpath/java/util/concurrent/locks/Condition.java new file mode 100644 index 0000000000..7a021eb289 --- /dev/null +++ b/classpath/java/util/concurrent/locks/Condition.java @@ -0,0 +1,24 @@ +/* Copyright (c) 2008-2014, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.concurrent.locks; + +import java.util.Date; +import java.util.concurrent.TimeUnit; + +public interface Condition { + public void await(); + public boolean await(long time, TimeUnit unit); + public long awaitNanos(long nanosTimeout); + public void awaitUninterruptibly(); + public boolean awaitUntil(Date deadline); + public void signal(); + public void signalAll(); +} diff --git a/classpath/java/util/concurrent/locks/Lock.java b/classpath/java/util/concurrent/locks/Lock.java new file mode 100644 index 0000000000..f2fb9b0792 --- /dev/null +++ b/classpath/java/util/concurrent/locks/Lock.java @@ -0,0 +1,22 @@ +/* Copyright (c) 2008-2014, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.concurrent.locks; + +import java.util.concurrent.TimeUnit; + +public interface Lock { + public void lock(); + public void lockInterruptibly() throws InterruptedException; + public Condition newCondition(); + public boolean tryLock(); + public boolean tryLock(long time, TimeUnit unit) throws InterruptedException; + public void unlock(); +} diff --git a/classpath/java/util/concurrent/locks/LockSupport.java b/classpath/java/util/concurrent/locks/LockSupport.java new file mode 100644 index 0000000000..1f547c465d --- /dev/null +++ b/classpath/java/util/concurrent/locks/LockSupport.java @@ -0,0 +1,89 @@ +/* Copyright (c) 2008-2014, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.concurrent.locks; + +import sun.misc.Unsafe; + +public class LockSupport { + private LockSupport() { + // can't construct + } + + private static final Unsafe unsafe; + private static final long parkBlockerOffset; + + static { + unsafe = Unsafe.getUnsafe(); + try { + parkBlockerOffset = unsafe.objectFieldOffset(java.lang.Thread.class.getDeclaredField("parkBlocker")); + } catch (Exception ex) { + throw new Error(ex); + } + } + + private static void setBlocker(Thread t, Object arg) { + unsafe.putObject(t, parkBlockerOffset, arg); + } + + public static void unpark(Thread thread) { + if (thread != null) { + unsafe.unpark(thread); + } + } + + public static void park(Object blocker) { + doParkNanos(blocker, 0L); + } + + public static void parkNanos(Object blocker, long nanos) { + if (nanos <= 0) { + return; + } + + doParkNanos(blocker, nanos); + } + + private static void doParkNanos(Object blocker, long nanos) { + Thread t = Thread.currentThread(); + setBlocker(t, blocker); + unsafe.park(false, nanos); + setBlocker(t, null); + } + + public static void parkUntil(Object blocker, long deadline) { + Thread t = Thread.currentThread(); + setBlocker(t, blocker); + unsafe.park(true, deadline); + setBlocker(t, null); + } + + public static Object getBlocker(Thread t) { + if (t == null) { + throw new NullPointerException(); + } + + return unsafe.getObjectVolatile(t, parkBlockerOffset); + } + + public static void park() { + unsafe.park(false, 0L); + } + + public static void parkNanos(long nanos) { + if (nanos > 0) { + unsafe.park(false, nanos); + } + } + + public static void parkUntil(long deadline) { + unsafe.park(true, deadline); + } +} diff --git a/classpath/java/util/concurrent/locks/ReadWriteLock.java b/classpath/java/util/concurrent/locks/ReadWriteLock.java new file mode 100644 index 0000000000..a4804e5fa4 --- /dev/null +++ b/classpath/java/util/concurrent/locks/ReadWriteLock.java @@ -0,0 +1,16 @@ +/* Copyright (c) 2008-2014, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.concurrent.locks; + +public interface ReadWriteLock { + public Lock readLock(); + public Lock writeLock(); +} diff --git a/src/classpath-avian.cpp b/src/classpath-avian.cpp index dbbf821828..e49d4fa0c1 100644 --- a/src/classpath-avian.cpp +++ b/src/classpath-avian.cpp @@ -52,7 +52,7 @@ class MyClasspath : public Classpath { const unsigned NormalPriority = 5; return vm::makeThread - (t, 0, 0, 0, 0, NewState, NormalPriority, 0, 0, 0, + (t, 0, 0, 0, 0, 0, NewState, NormalPriority, 0, 0, 0, root(t, Machine::AppLoader), 0, 0, group, 0); }