add bare-bones ConcurrentLinkedQueue implementation

This commit is contained in:
Joel Dice 2011-09-29 18:26:50 -06:00
parent a8bb0d074b
commit 296cb74847
3 changed files with 125 additions and 0 deletions

View File

@ -0,0 +1,10 @@
package avian;
import java.lang.reflect.Field;
public class Atomic {
public static native long getOffset(Field field);
public static native boolean compareAndSwapObject
(Object o, long offset, Object old, Object new_);
}

View File

@ -0,0 +1,88 @@
package java.util.concurrent;
import avian.Atomic;
public class ConcurrentLinkedQueue<T> {
private static final long QueueHead;
private static final long QueueTail;
private static final long NodeNext;
static {
try {
QueueHead = Atomic.getOffset
(ConcurrentLinkedQueue.class.getField("head"));
QueueTail = Atomic.getOffset
(ConcurrentLinkedQueue.class.getField("tail"));
NodeNext = Atomic.getOffset
(Node.class.getField("next"));
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
}
}
private volatile Node<T> head = new Node(null, null);
private volatile Node<T> tail = head;
public boolean add(T value) {
Node<T> n = new Node(value, null);
while (true) {
Node<T> t = tail;
Node<T> next = tail.next;
if (t == tail) {
if (next != null) {
Atomic.compareAndSwapObject(this, QueueTail, t, next);
} else if (Atomic.compareAndSwapObject(tail, NodeNext, null, n)) {
Atomic.compareAndSwapObject(this, QueueTail, t, n);
break;
}
}
}
return true;
}
public T peek() {
return poll(false);
}
public T poll() {
return poll(true);
}
public T poll(boolean remove) {
while (true) {
Node<T> h = head;
Node<T> t = tail;
Node<T> next = head.next;
if (h == head) {
if (h == t) {
if (next != null) {
Atomic.compareAndSwapObject(this, QueueTail, t, next);
} else {
return null;
}
} else {
T value = next.value;
if ((! remove)
|| Atomic.compareAndSwapObject(this, QueueHead, h, next))
{
return value;
}
}
}
}
}
private static class Node<T> {
public volatile T value;
public volatile Node<T> next;
public Node(T value, Node<T> next) {
this.value = value;
this.next = next;
}
}
}

View File

@ -605,6 +605,33 @@ Avian_java_lang_Thread_yield
t->m->system->yield(); t->m->system->yield();
} }
extern "C" JNIEXPORT int64_t JNICALL
Avian_avian_Atomic_getOffset
(Thread* t, object, uintptr_t* arguments)
{
return fieldOffset
(t, jfieldVmField(t, reinterpret_cast<object>(arguments[0])));
}
extern "C" JNIEXPORT int64_t JNICALL
Avian_avian_Atomic_compareAndSwapObject
(Thread* t, object, uintptr_t* arguments)
{
object target = reinterpret_cast<object>(arguments[0]);
int64_t offset; memcpy(&offset, arguments + 1, 8);
uintptr_t expect = arguments[3];
uintptr_t update = arguments[4];
bool success = atomicCompareAndSwap
(&cast<uintptr_t>(target, offset), expect, update);
if (success) {
mark(t, target, offset);
}
return success;
}
extern "C" JNIEXPORT int64_t JNICALL extern "C" JNIEXPORT int64_t JNICALL
Avian_avian_Classes_primitiveClass Avian_avian_Classes_primitiveClass
(Thread* t, object, uintptr_t* arguments) (Thread* t, object, uintptr_t* arguments)