
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