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

org.jctools.queues.atomic.unpadded.SpscLinkedAtomicUnpaddedQueue Maven / Gradle / Ivy

There is a newer version: 1.52.1
Show newest version
/*
 * 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 org.jctools.queues.atomic.unpadded;

import java.util.concurrent.atomic.*;
import org.jctools.queues.*;
import static org.jctools.queues.atomic.AtomicQueueUtil.*;
import org.jctools.queues.atomic.LinkedQueueAtomicNode;

/**
 * NOTE: This class was automatically generated by org.jctools.queues.atomic.unpadded.JavaParsingAtomicUnpaddedLinkedQueueGenerator
 * which can found in the jctools-build module. The original source file is SpscLinkedQueue.java.
 *
 * This is a weakened version of the MPSC algorithm as presented
 *  on
 * 1024 Cores by D. Vyukov. The original has been adapted to Java and it's quirks with regards to memory
 * model and layout:
 * 
    *
  1. Use inheritance to ensure no false sharing occurs between producer/consumer node reference fields. *
  2. As this is an SPSC we have no need for XCHG, an ordered store is enough. *
* The queue is initialized with a stub node which is set to both the producer and consumer node references. * From this point follow the notes on offer/poll. * * @param * @author nitsanw */ public class SpscLinkedAtomicUnpaddedQueue extends BaseLinkedAtomicUnpaddedQueue { public SpscLinkedAtomicUnpaddedQueue() { LinkedQueueAtomicNode node = newNode(); spProducerNode(node); spConsumerNode(node); // this ensures correct construction: StoreStore node.soNext(null); } /** * {@inheritDoc}
*

* IMPLEMENTATION NOTES:
* Offer is allowed from a SINGLE thread.
* Offer allocates a new node (holding the offered value) and: *

    *
  1. Sets the new node as the producerNode *
  2. Sets that node as the lastProducerNode.next *
* From this follows that producerNode.next is always null and for all other nodes node.next is not null. * * @see MessagePassingQueue#offer(Object) * @see java.util.Queue#offer(java.lang.Object) */ @Override public boolean offer(final E e) { if (null == e) { throw new NullPointerException(); } final LinkedQueueAtomicNode nextNode = newNode(e); LinkedQueueAtomicNode oldNode = lpProducerNode(); soProducerNode(nextNode); // Should a producer thread get interrupted here the chain WILL be broken until that thread is resumed // and completes the store in prev.next. This is a "bubble". // Inverting the order here will break the `isEmpty` invariant, and will require matching adjustments elsewhere. oldNode.soNext(nextNode); return true; } @Override public int fill(Supplier s) { return MessagePassingQueueUtil.fillUnbounded(this, s); } @Override public int fill(Supplier s, int limit) { if (null == s) throw new IllegalArgumentException("supplier is null"); if (limit < 0) throw new IllegalArgumentException("limit is negative:" + limit); if (limit == 0) return 0; LinkedQueueAtomicNode tail = newNode(s.get()); final LinkedQueueAtomicNode head = tail; for (int i = 1; i < limit; i++) { final LinkedQueueAtomicNode temp = newNode(s.get()); // spNext : soProducerNode ensures correct construction tail.spNext(temp); tail = temp; } final LinkedQueueAtomicNode oldPNode = lpProducerNode(); soProducerNode(tail); // same bubble as offer, and for the same reasons. oldPNode.soNext(head); return limit; } @Override public void fill(Supplier s, WaitStrategy wait, ExitCondition exit) { MessagePassingQueueUtil.fill(this, s, wait, exit); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy