|
@ -6,30 +6,53 @@ package server.util; |
|
|
trying to implement a wait-free queue |
|
|
trying to implement a wait-free queue |
|
|
*/ |
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
import java.util.concurrent.atomic.AtomicInteger; |
|
|
|
|
|
import java.util.concurrent.atomic.AtomicMarkableReference; |
|
|
import java.util.concurrent.atomic.AtomicReferenceArray; |
|
|
import java.util.concurrent.atomic.AtomicReferenceArray; |
|
|
|
|
|
|
|
|
public class Queue<T> { |
|
|
public class Queue<T> { |
|
|
|
|
|
|
|
|
private volatile int head = 0, tail = 0; |
|
|
|
|
|
|
|
|
private AtomicMarkableReference<Integer> head, tail; |
|
|
private final int capacity; |
|
|
private final int capacity; |
|
|
private AtomicReferenceArray<T> items; |
|
|
private AtomicReferenceArray<T> items; |
|
|
|
|
|
|
|
|
public Queue(int capacity) { |
|
|
public Queue(int capacity) { |
|
|
this.capacity = capacity; |
|
|
this.capacity = capacity; |
|
|
items = new AtomicReferenceArray<>(capacity); |
|
|
|
|
|
|
|
|
this.head = new AtomicMarkableReference(0, false); |
|
|
|
|
|
this.tail = new AtomicMarkableReference(0, false); |
|
|
|
|
|
items = new AtomicReferenceArray<T>(capacity); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public boolean enq(T x) { |
|
|
public boolean enq(T x) { |
|
|
if (tail - head == capacity) return false; |
|
|
|
|
|
items.set((tail + 1) % capacity, x); |
|
|
|
|
|
tail++; |
|
|
|
|
|
|
|
|
boolean[] mark = new boolean[1]; |
|
|
|
|
|
if (tail.get(mark) - head.get(mark) == capacity) return false; |
|
|
|
|
|
int tmp; |
|
|
|
|
|
do { |
|
|
|
|
|
tmp = tail.get(mark); |
|
|
|
|
|
System.out.println("enq: " + x); |
|
|
|
|
|
System.out.println("val tmp: " + tmp); |
|
|
|
|
|
System.out.println("val tmp: " + next(tmp)); |
|
|
|
|
|
items.compareAndSet(tmp, null, x); |
|
|
|
|
|
} while (tail.compareAndSet(tmp, next(tmp), true, false)); |
|
|
|
|
|
System.out.println("head: " + head.getReference() + "\ntail: " + tail.getReference() + "\ndiff: " + (tail.getReference() - head.getReference())); |
|
|
return true; |
|
|
return true; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public T deq() { |
|
|
public T deq() { |
|
|
if (tail - head == 0) return null; |
|
|
|
|
|
T x = items.get((head + 1) % capacity); |
|
|
|
|
|
head++; |
|
|
|
|
|
|
|
|
boolean[] mark = new boolean[1]; |
|
|
|
|
|
System.out.println("test: " + (tail.get(mark) - head.get(mark)) + "\ncap: " + capacity); |
|
|
|
|
|
if (tail.get(mark) - head.get(mark) == 0) return null; |
|
|
|
|
|
int tmp; |
|
|
|
|
|
T x; |
|
|
|
|
|
do { |
|
|
|
|
|
tmp = head.get(mark); |
|
|
|
|
|
System.out.println("head: " + next(tmp)); |
|
|
|
|
|
x = items.getAndSet(tmp, null); |
|
|
|
|
|
} while (head.compareAndSet(tmp, next(tmp), false, true)); |
|
|
return x; |
|
|
return x; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private int next(int x) { |
|
|
|
|
|
return (x + 1) % capacity; |
|
|
|
|
|
} |
|
|
} |
|
|
} |