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

com.bloomberg.selekt.commons.LinkedDeque.kt Maven / Gradle / Ivy

/*
 * Copyright 2020 Bloomberg Finance L.P.
 *
 * 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
 *
 *     https://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 com.bloomberg.selekt.commons

import javax.annotation.concurrent.NotThreadSafe

@NotThreadSafe
internal class LinkedDeque {
    @NotThreadSafe
    @PublishedApi
    internal data class Node(
        @JvmField
        var item: T?,
        @JvmField
        var previous: Node?,
        @JvmField
        var next: Node?
    ) {
        fun clear() = apply {
            item = null
            previous = null
            next = null
        }
    }
    private var pool: Node? = null

    private val emptyIterator = emptyLinkedDequeMutableIterator()

    @JvmField
    var first: Node? = null
    private var last: Node? = null

    val isEmpty: Boolean
        get() = first == null

    val hasSizeOne: Boolean
        get() = first === last && first != null

    inline fun pollFirst(predicate: (T) -> Boolean): T? {
        var head = first
        while (head != null) {
            if (predicate(head.item!!)) {
                return unlink(head)
            }
            head = head.next
        }
        return null
    }

    fun pollLast() = last?.let {
        last = it.previous
        if (it === first) {
            first = null
        } else {
            it.previous!!.next = null
        }
        it.item.also { _ -> recycle(it) }
    }

    fun putFirst(item: T) {
        val head = first
        first = acquireNode(item)
        if (head == null) {
            last = first
        } else {
            head.previous = first
        }
    }

    fun reverseMutableIterator(): MutableIterator = last.let {
        if (it != null) LinkedDequeReversedIterator(this, it) else emptyIterator
    }

    fun unlink(node: Node) = node.run {
        next.let {
            if (it != null) {
                it.previous = previous
            } else {
                last = previous
            }
        }
        previous.let {
            if (it != null) {
                it.next = next
            } else {
                first = next
            }
        }
        item.also { recycle(this) }
    }

    private fun acquireNode(item: T): Node {
        pool?.also {
            pool = null
            it.item = item
            it.next = first
            return@acquireNode it
        }
        return Node(item, null, first)
    }

    private fun recycle(node: Node) {
        if (pool != null) {
            return
        }
        pool = node.clear()
    }
}

private class LinkedDequeReversedIterator(
    private val deque: LinkedDeque,
    last: LinkedDeque.Node
) : MutableIterator {
    private var head = LinkedDeque.Node(last.item, last, null)

    override fun hasNext() = head.previous != null

    override fun next() = (head.previous ?: throw NoSuchElementException()).also {
        head.previous = it.previous
        head.next = it
    }.item!!

    override fun remove() {
        deque.unlink(head.next!!)
    }
}

private fun  emptyLinkedDequeMutableIterator() = object : MutableIterator {
    override fun hasNext() = false

    override fun next() = throw NoSuchElementException()

    override fun remove() = throw UnsupportedOperationException()
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy