rx.internal.util.MpscPaddedQueue Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of rxjava-core Show documentation
Show all versions of rxjava-core Show documentation
rxjava-core developed by Netflix
/**
* Copyright 2014 Netflix, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package rx.internal.util;
import static java.util.concurrent.atomic.AtomicReferenceFieldUpdater.newUpdater;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
import rx.internal.util.MpscPaddedQueue.Node;
abstract class MpscLinkedQueuePad0 {
long p00, p01, p02, p03, p04, p05, p06, p07;
long p30, p31, p32, p33, p34, p35, p36, p37;
}
abstract class MpscLinkedQueueHeadRef extends MpscLinkedQueuePad0 {
@SuppressWarnings("rawtypes")
private static final AtomicReferenceFieldUpdater UPDATER =
newUpdater(MpscLinkedQueueHeadRef.class, Node.class, "headRef");
private volatile Node headRef;
protected final Node headRef() {
return headRef;
}
protected final void headRef(Node val) {
headRef = val;
}
protected final void lazySetHeadRef(Node newVal) {
UPDATER.lazySet(this, newVal);
}
}
abstract class MpscLinkedQueuePad1 extends MpscLinkedQueueHeadRef {
long p00, p01, p02, p03, p04, p05, p06, p07;
long p30, p31, p32, p33, p34, p35, p36, p37;
}
abstract class MpscLinkedQueueTailRef extends MpscLinkedQueuePad1 {
@SuppressWarnings("rawtypes")
private static final AtomicReferenceFieldUpdater UPDATER =
newUpdater(MpscLinkedQueueTailRef.class, Node.class, "tailRef");
private volatile Node tailRef;
protected final Node tailRef() {
return tailRef;
}
protected final void tailRef(Node val) {
tailRef = val;
}
@SuppressWarnings("unchecked")
protected final Node getAndSetTailRef(Node newVal) {
return (Node) UPDATER.getAndSet(this, newVal);
}
}
/**
* A multiple-producer single consumer queue implementation with padded reference to tail to avoid cache-line
* thrashing. Based on Netty's MpscQueue implementation
* but using {@code AtomicReferenceFieldUpdater} instead of {@code Unsafe}.
* Original algorithm presented on 1024
* Cores by D. Vyukov.
* Data structure modified to avoid false sharing between head and tail references as per implementation of
* MpscLinkedQueue on JCTools project.
*
* @param the element type
*/
public final class MpscPaddedQueue extends MpscLinkedQueueTailRef {
long p00, p01, p02, p03, p04, p05, p06, p07;
long p30, p31, p32, p33, p34, p35, p36, p37;
/**
* Initializes the empty queue.
*/
public MpscPaddedQueue() {
Node stub = new Node(null);
headRef(stub);
tailRef(stub);
}
/**
* Offer a new value.
*
* @param v the value to offer
*/
public void offer(E v) {
Node n = new Node(v);
getAndSetTailRef(n).next(n);
}
/**
* @warn method description missing
* @return Poll a value from the head of the queue or return null if the queue is empty.
*/
public E poll() {
Node n = peekNode();
if (n == null) {
return null;
}
E v = n.value;
n.value = null; // do not retain this value as the node still stays in the queue
lazySetHeadRef(n);
return v;
}
/**
* Check if there is a node available without changing anything.
* @return
*/
private Node peekNode() {
for (;;) {
Node t = headRef();
Node n = t.next();
if (n != null || headRef() == t) {
return n;
}
}
}
/**
* Clears the queue.
*/
public void clear() {
for (;;) {
if (poll() == null) {
break;
}
}
}
/**
* Regular node with value and reference to the next node.
*/
static final class Node {
E value;
@SuppressWarnings(value = "rawtypes")
static final AtomicReferenceFieldUpdater TAIL_UPDATER = AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "next");
private volatile Node next;
Node(E value) {
this.value = value;
}
void next(Node newNext) {
TAIL_UPDATER.lazySet(this, newNext);
}
Node next() {
return next;
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy