Skip to content

Commit 2781a5e

Browse files
committed
Merge branch 'master' into feature/combat
2 parents 50fec70 + bed66e9 commit 2781a5e

File tree

2 files changed

+75
-13
lines changed

2 files changed

+75
-13
lines changed

common/src/main/kotlin/com/lambda/module/modules/network/PacketLimiter.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ object PacketLimiter : Module(
4141
}
4242
private val interval by setting("Duration", 1000L, 1L..1000L, 50L, "The interval / duration in milliseconds to limit packets for", unit = " ms").apply {
4343
onValueChange { _, to ->
44-
packetQueue.setInterval(to)
44+
packetQueue.setDecayTime(to)
4545
}
4646
}
4747

common/src/main/kotlin/com/lambda/util/collections/LimitedDecayQueue.kt

Lines changed: 74 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,39 +20,101 @@ package com.lambda.util.collections
2020
import java.time.Instant
2121
import java.util.concurrent.ConcurrentLinkedQueue
2222

23+
/**
24+
* A thread-safe collection that limits the number of elements it can hold and automatically removes elements
25+
* older than a specified time interval. The elements are stored with the timestamp of their addition to the collection.
26+
*
27+
* @param E The type of elements held in this collection.
28+
* @property sizeLimit The maximum number of elements the queue can hold at any given time.
29+
* @property maxAge The age (in milliseconds) after which elements are considered expired and are removed from the queue.
30+
*/
2331
class LimitedDecayQueue<E>(
2432
private var sizeLimit: Int,
25-
private var interval: Long,
26-
) : ConcurrentLinkedQueue<Pair<E, Instant>>() {
33+
private var maxAge: Long,
34+
) : AbstractMutableCollection<E>() {
35+
private val queue: ConcurrentLinkedQueue<Pair<E, Instant>> = ConcurrentLinkedQueue()
36+
37+
override val size: Int
38+
get() {
39+
cleanUp()
40+
return queue.size
41+
}
42+
43+
override fun iterator(): MutableIterator<E> {
44+
cleanUp()
45+
return queue.map { it.first }.iterator() as MutableIterator<E>
46+
}
47+
2748
@Synchronized
28-
@JvmName("jvmAdd")
29-
fun add(element: E): Boolean {
49+
override fun add(element: E): Boolean {
3050
cleanUp()
31-
return if (size < sizeLimit) {
32-
add(element to Instant.now())
51+
return if (queue.size < sizeLimit) {
52+
queue.add(element to Instant.now())
3353
true
3454
} else {
3555
false
3656
}
3757
}
3858

3959
@Synchronized
40-
fun setMaxSize(newSize: Int) {
41-
sizeLimit = newSize
60+
override fun addAll(elements: Collection<E>): Boolean {
61+
cleanUp()
62+
val spaceAvailable = sizeLimit - queue.size
63+
val elementsToAdd = elements.take(spaceAvailable)
64+
val added = elementsToAdd.map { queue.add(it to Instant.now()) }
65+
return added.any { it }
66+
}
67+
68+
@Synchronized
69+
override fun remove(element: E): Boolean {
4270
cleanUp()
71+
return queue.removeIf { it.first == element }
4372
}
4473

4574
@Synchronized
46-
fun setInterval(newInterval: Long) {
47-
interval = newInterval
75+
override fun removeAll(elements: Collection<E>): Boolean {
4876
cleanUp()
77+
return queue.removeIf { it.first in elements }
4978
}
5079

5180
@Synchronized
81+
override fun retainAll(elements: Collection<E>): Boolean {
82+
cleanUp()
83+
return queue.removeIf { it.first !in elements }
84+
}
85+
86+
@Synchronized
87+
override fun clear() {
88+
queue.clear()
89+
}
90+
91+
/**
92+
* Updates the maximum allowed size for the queue and triggers a cleanup operation
93+
* to remove elements exceeding the new size or falling outside the allowed time interval.
94+
*
95+
* @param newSize The new maximum size for the queue. Must be a non-negative integer.
96+
*/
97+
fun setMaxSize(newSize: Int) {
98+
sizeLimit = newSize
99+
cleanUp()
100+
}
101+
102+
/**
103+
* Sets the decay time for the elements in the queue. The decay time determines the
104+
* maximum age that any element in the queue can have before being considered expired
105+
* and removed. Updates the internal state and triggers a cleanup of expired elements.
106+
*
107+
* @param decayTime The decay time in milliseconds. Must be a non-negative value.
108+
*/
109+
fun setDecayTime(decayTime: Long) {
110+
maxAge = decayTime
111+
cleanUp()
112+
}
113+
52114
private fun cleanUp() {
53115
val now = Instant.now()
54-
while (isNotEmpty() && now.minusMillis(interval).isAfter(peek().second)) {
55-
poll()
116+
while (queue.isNotEmpty() && now.minusMillis(maxAge).isAfter(queue.peek().second)) {
117+
queue.poll()
56118
}
57119
}
58120
}

0 commit comments

Comments
 (0)