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

co.paralleluniverse.concurrent.util.SingleConsumerNonblockingProducerDelayQueue Maven / Gradle / Ivy

/*
 * Copyright (c) 2013-2014, 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.concurrent.util;

import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

/**
 *
 * @author pron
 */
public class SingleConsumerNonblockingProducerDelayQueue extends SingleConsumerNonblockingProducerQueue {
    public SingleConsumerNonblockingProducerDelayQueue() {
        super(new ConcurrentSkipListPriorityQueue());
    }

    @Override
    public E poll() {
        final E first = peek();
        if (first == null || !isExpired(first))
            return null;
        return super.poll(); // this could be a different element from first, but its expiration must be earlier, so it doesn't matter
    }

    @Override
    public E take() throws InterruptedException {
        E e = q.peek();
        long delayNanos;
        if (e == null || getDelay(e) > 0) {
            sync.register();
            try {
                e = q.peek();
                delayNanos = getDelay(e);

                while (delayNanos > 0) {
                    sync.awaitNanos(delayNanos);
                    e = q.peek();
                    delayNanos = getDelay(e);
                }
                return q.poll(); // this may not be e, but if not, it must be an element with expiration <= e.
            } finally {
                sync.unregister();
            }
        } else {
            e = q.poll();
            assert e != null;
            return e;
        }
    }

    @Override
    public E poll(long timeout, TimeUnit unit) throws InterruptedException {
        E e = q.peek();
        long delayNanos;
        if (e == null || getDelay(e) > 0) {
            long left = unit.toNanos(timeout);
            sync.register();
            try {
                e = q.peek();
                delayNanos = getDelay(e);

                while (left > 0 & delayNanos > 0) {
                    left = sync.awaitNanos(Math.min(left, delayNanos));
                    e = q.peek();
                    delayNanos = getDelay(e);
                }
                return delayNanos > 0 ? null : q.poll();
            } finally {
                sync.unregister();
            }
        } else {
            e = q.poll();
            assert e != null;
            return e;
        }
    }

    private long getDelay(E e) {
        return e != null ? e.getDelay(TimeUnit.NANOSECONDS) : Long.MAX_VALUE;
    }

    protected boolean isExpired(E e) {
        return e.getDelay(TimeUnit.NANOSECONDS) <= 0;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy