All Downloads are FREE. Search and download functionalities are using the official Maven repository.

rx.internal.util.MpscPaddedQueue Maven / Gradle / Ivy

There is a newer version: 0.20.7
Show newest version
/**
 * 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