Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Quasar: lightweight threads and actors for the JVM.
* Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.
*
* This program and the accompanying materials are dual-licensed under
* either the terms of the Eclipse Public License v1.0 as published by
* the Eclipse Foundation
*
* or (per the licensee's choosing)
*
* under the terms of the GNU Lesser General Public License version 3.0
* as published by the Free Software Foundation.
*/
package co.paralleluniverse.strands.queues;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
/**
*
* @author pron
*/
public abstract class CircularBuffer implements BasicQueue {
final int capacity;
final int mask;
private final boolean singleProducer;
volatile long p101, p102, p103, p104, p105, p106, p107;
volatile long tail; // next element to be written
volatile long p201, p202, p203, p204, p205, p206, p207;
volatile long lastWritten; // follows tail
volatile Object p301, p302, p303, p304, p305, p306, p307;
final Consumer consumer;
CircularBuffer(int capacity, boolean singleProducer) {
// capacity is a power of 2
this.capacity = nextPowerOfTwo(capacity);
this.mask = this.capacity - 1;
this.singleProducer = singleProducer;
this.consumer = newConsumer();
}
public boolean isSingleProducer() {
return singleProducer;
}
public Consumer builtinConsumer() {
return consumer;
}
private static int nextPowerOfTwo(int v) {
assert v >= 0;
return 1 << (32 - Integer.numberOfLeadingZeros(v - 1));
}
@Override
public int capacity() {
return capacity;
}
final long preEnq() {
long t;
if (singleProducer) {
t = tail;
tail++; // orderedSetTail(t + 1); //
} else {
do {
t = tail;
} while (!casTail(t, t + 1));
}
return t;
}
final void postEnq() {
if (singleProducer)
lastWritten++;
else {
long w;
do {
w = lastWritten;
} while (!casLastWritten(w, w + 1));
}
}
@Override
public abstract boolean enq(E elem);
@Override
public E poll() {
return consumer.poll();
}
@Override
public int size() {
return consumer.size();
}
@Override
public boolean isEmpty() {
return consumer.isEmpty();
}
public boolean hasNext() {
return consumer.hasNext();
}
public abstract Consumer newConsumer();
public abstract class Consumer {
long head;
public final long lastIndexRead() {
return head - 1;
}
public final boolean hasNext() {
return tail > head;
}
public void poll0() {
assert tail > head;
int headStart = 0; // how many elements ahead of tail we'll try to read if tail progresses too fast
int attempt = 0;
for (;;) {
while (lastWritten <= head) // wait for enq to complete
;
grabValue((int) head & mask);
final long oldest = tail - capacity;
if (head >= oldest) {
head++;
return;
}
// tail has overtaken us
head = oldest + headStart; // < tail
if (attempt > 30)
throw new RuntimeException("Can't catch up with producer");
// increasing headStart diesn't work for some reason. it breaks monotonicity somehow...
// if ((++attempt & 0x03) == 0) { // every 4 attempts inc headStart
// headStart++;
// if (headStart >= capacity)
// throw new RuntimeException("Can't catch up with producer");
// }
attempt++;
}
}
public E poll() {
if (!hasNext())
return null;
poll0();
final E v = getValue();
clearValue(); // for gc
return v;
}
public E getAndClearReadValue() {
final E v = getValue();
clearValue(); // for gc
return v;
}
public int size() {
return (int) (tail - head);
}
public boolean isEmpty() {
return tail == head;
}
protected abstract void grabValue(int index);
protected abstract void clearValue();
protected abstract E getValue();
}
////////////////////////////////////////////////////////////////////////
private static final VarHandle TAIL;
private static final VarHandle LAST_WRITTEN;
static {
try {
MethodHandles.Lookup l = MethodHandles.lookup();
TAIL = l.findVarHandle(CircularBuffer.class, "tail", long.class);
LAST_WRITTEN = l.findVarHandle(CircularBuffer.class, "lastWritten", long.class);
} catch (ReflectiveOperationException e) {
throw new ExceptionInInitializerError(e);
}
}
private void orderedSetTail(long value) {
TAIL.setOpaque(this, value); // UNSAFE.putOrderedLong(this, tailOffset, value);
}
boolean casTail(long expected, long update) {
return TAIL.compareAndSet(this, expected, update);
}
boolean casLastWritten(long expected, long update) {
return LAST_WRITTEN.compareAndSet(this, expected, update);
}
}