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

co.paralleluniverse.strands.queues.SingleConsumerLinkedArrayPrimitiveQueue Maven / Gradle / Ivy

Go to download

The core library for Fibers on Java, compatible with Java 11-16. Forked from puniverse/quasar

There is a newer version: 10.0.6
Show newest version
/*
 * 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;
import java.util.NoSuchElementException;

/**
 *
 * @author pron
 */
public abstract class SingleConsumerLinkedArrayPrimitiveQueue extends SingleConsumerLinkedArrayQueue {

    boolean enqRaw(long item) {
        final Node node;
        final int index;
        final int blockSize = blockSize();
        Node nn = null;
        for (;;) {
            final PrimitiveNode t = (PrimitiveNode) tail;
            final int i = t.tailIndex;

            if (i < blockSize) {
                if (compareAndSetTailIndex(t, i, i + 1)) {
                    node = t;
                    index = i;
                    break;
                }
                // backoff();
            } else {
                if (nn == null)
                    nn = newNode();
                nn.prev = t;
                if (compareAndSetTail(t, nn)) {
                    t.next = nn;
                    nn = null;
                } else
                    backoff();
            }
        }

        enqRaw(node, index, item);

        if (true) {
            final PrimitiveNode n = (PrimitiveNode) node;
            while (n.maxReadIndex != index)
                ;
            n.maxReadIndex = index + 1;
        } else {
            while (!compareAndSetMaxReadIndex(node, index, index + 1))
                ;
        }
        return true;
    }

    long pollRaw() {
        final long raw = peekRaw();
        deqHead();
        return raw;
    }

    private long peekRaw() {
        if (!prePeek())
            throw new NoSuchElementException();
        return getRaw(head, headIndex);
    }

    abstract void enqRaw(Node n, int i, long item);

    abstract long getRaw(Node n, int i);

    @Override
    boolean hasValue(Node n, int index) {
        return index < ((PrimitiveNode) n).maxReadIndex;
    }

    @Override
    boolean isDeleted(Node n, int index) {
        return getBit(((PrimitiveNode) n).deleted, index);
    }

    @Override
    void markDeleted(Node n1, int index) {
        assert index <= blockSize();
        final PrimitiveNode n = (PrimitiveNode) n1;
        n.deleted = setBit(n.deleted, index);
    }

    static abstract class PrimitiveNode extends Node {
        volatile int tailIndex;
        volatile int maxReadIndex;
        short deleted;
    }

    private static short setBit(short bits, int index) {
        return (short) (bits | (1 << index));
    }

    private static boolean getBit(short bits, int index) {
        return (bits >>> index & 1) != 0;
    }

    private static final VarHandle TAIL_INDEX;
    private static final VarHandle MAX_READ_INDEX;

    static {
        try {
            MethodHandles.Lookup l = MethodHandles.lookup();
            TAIL_INDEX     = l.findVarHandle(PrimitiveNode.class, "tailIndex",    int.class);
            MAX_READ_INDEX = l.findVarHandle(PrimitiveNode.class, "maxReadIndex", int.class);
        } catch (ReflectiveOperationException e) {
            throw new ExceptionInInitializerError(e);
        }
    }

    private boolean compareAndSetTailIndex(Node n, int expect, int update) {
        return TAIL_INDEX.compareAndSet((PrimitiveNode) n, expect, update);
    }

    private boolean compareAndSetMaxReadIndex(Node n, int expect, int update) {
        return MAX_READ_INDEX.compareAndSet((PrimitiveNode) n, expect, update);
    }

//    private static final long tailIndexOffset;
//    private static final long maxReadIndexOffset;
//
//    static {
//        try {
//            tailIndexOffset = UNSAFE.objectFieldOffset(PrimitiveNode.class.getDeclaredField("tailIndex"));
//            maxReadIndexOffset = UNSAFE.objectFieldOffset(PrimitiveNode.class.getDeclaredField("maxReadIndex"));
//        } catch (Exception ex) {
//            throw new Error(ex);
//        }
//    }
//
//    private boolean compareAndSetTailIndex(Node n, int expect, int update) {
//        return UNSAFE.compareAndSwapInt((PrimitiveNode) n, tailIndexOffset, expect, update);
//    }
//
//    private boolean compareAndSetMaxReadIndex(Node n, int expect, int update) {
//        return UNSAFE.compareAndSwapInt((PrimitiveNode) n, maxReadIndexOffset, expect, update);
//    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy