001/**
002 * The MIT License (MIT)
003 *
004 * Copyright (c) 2019 nobark (tools4j), Marco Terzer, Anton Anufriev
005 *
006 * Permission is hereby granted, free of charge, to any person obtaining a copy
007 * of this software and associated documentation files (the "Software"), to deal
008 * in the Software without restriction, including without limitation the rights
009 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
010 * copies of the Software, and to permit persons to whom the Software is
011 * furnished to do so, subject to the following conditions:
012 *
013 * The above copyright notice and this permission notice shall be included in all
014 * copies or substantial portions of the Software.
015 *
016 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
017 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
018 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
019 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
020 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
021 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
022 * SOFTWARE.
023 */
024package org.tools4j.nobark.queue;
025
026import java.util.function.BiConsumer;
027
028/**
029 * A conflation queue is a queue with a safety mechanism to prevent overflow.  Values are enqueued with a conflation
030 * key, and if a value with the same key already resides in the queue then the two values will be "conflated".
031 * Conflation in the simplest case means that the most recent value survives and replaces older values;  some more
032 * advanced implementations support merging when conflation occurs.
033 *
034 * @param <K> the type of the conflation key
035 * @param <V> the type of values in the queue
036 */
037public interface ConflationQueue<K,V> {
038    /**
039     * Returns the appender object used by the producer to enqueue values.  Some conflation queue implementations return
040     * thread-safe appender instances, other implementations return an instance per caller thread.  Hence it is highly
041     * recommended to access the appender via this method directly from the producer thread and not share it between
042     * threads.
043     *
044     * @return the appender object used to enqueue values
045     */
046    Appender<K,V> appender();
047
048    /**
049     * Returns the poller object used by the consumer to poll values.  Some conflation queue implementations return
050     * thread-safe poller instances, other implementations return an instance per caller thread.  Hence it is highly
051     * recommended to access the poller via this method directly from the consumer thread and not share it between
052     * threads.
053     *
054     * @return the poller object used to poll values
055     */
056    Poller<K,V> poller();
057
058    /**
059     * Returns the number of elements in this queue.
060     *
061     * <p>Beware that, unlike in most collections, this method may
062     * <em>NOT</em> be a constant-time operation. Because of the
063     * asynchronous nature of concurrent queues, determining the current
064     * number of elements may require an O(n) traversal.
065     * Additionally, if elements are added or removed during execution
066     * of this method, the returned result may be inaccurate.  Thus,
067     * this method is typically not very useful in concurrent
068     * applications.
069     *
070     * @return the number of elements in this queue
071     */
072    int size();
073
074    /**
075     * Appender used by the producer to enqueue values.
076     *
077     * @param <K> the type of the conflation key
078     * @param <V> the type of values in the queue
079     */
080    interface Appender<K,V> {
081        /**
082         * Enqueue the specified value using the given conflation key.  If conflation occurred, the conflated value
083         * is returned.  If no conflation occurs, null is returned, or for {@link ExchangeConflationQueue}
084         * implementations an exchange value from the poller may be returned if present.
085         *
086         * @param conflationKey the conflation key
087         * @param value         the value to enqueue
088         * @return the conflated value if conflation occurred, or otherwise null or an exchange value from the poller
089         *         for {@link ExchangeConflationQueue} implementations
090         */
091        V enqueue(K conflationKey, V value);
092    }
093
094    /**
095     * Poller object used by the consumer to poll values.
096     *
097     * @param <K> the type of the conflation key
098     * @param <V> the type of values in the queue
099     */
100    interface Poller<K, V> {
101        /**
102         * Polls the queue passing a consumer which is invoked with conflation key and polled value if the queue was
103         * non-empty.  Returns the polled value if any value was present in the queue, or null if the queue was empty.
104         *
105         * @param consumer consumer for conflation key and polled value
106         * @return the polled value, or null if the queue was empty
107         */
108        V poll(BiConsumer<? super K, ? super V> consumer);
109
110        /**
111         * Polls the queue and returns the value if any value was present in the queue, or null if the queue was empty.
112         *
113         * @return the polled value, or null if the queue was empty
114         */
115        default V poll() {
116            return poll((k,v) -> {});
117        }
118    }
119}