@@ -19,7 +19,6 @@ import kotlinx.coroutines.Job
19
19
import kotlinx.coroutines.async
20
20
import kotlinx.coroutines.launch
21
21
import kotlinx.coroutines.sync.Mutex
22
- import kotlinx.coroutines.sync.Semaphore
23
22
import kotlinx.coroutines.withTimeout
24
23
import net.kyori.adventure.text.Component
25
24
import org.bukkit.Bukkit
@@ -32,7 +31,6 @@ import org.slf4j.LoggerFactory
32
31
import java.util.WeakHashMap
33
32
import java.util.concurrent.ConcurrentLinkedQueue
34
33
import java.util.concurrent.atomic.AtomicBoolean
35
- import java.util.concurrent.atomic.AtomicInteger
36
34
import kotlin.time.Duration
37
35
import kotlin.time.Duration.Companion.seconds
38
36
@@ -50,8 +48,8 @@ public abstract class AbstractInterfaceView<I : InterfacesInventory, T : Interfa
50
48
}
51
49
52
50
private val logger = LoggerFactory .getLogger(AbstractInterfaceView ::class .java)
53
- private val semaphore = Semaphore ( 1 )
54
- private val queue = AtomicInteger ( 0 )
51
+ private val paneMutex = Mutex ( )
52
+ private val debouncedRender = AtomicBoolean ( false )
55
53
56
54
private val children = WeakHashMap <AbstractInterfaceView <* , * , * >, Unit > ()
57
55
@@ -202,12 +200,14 @@ public abstract class AbstractInterfaceView<I : InterfacesInventory, T : Interfa
202
200
// Don't update if closed
203
201
if (! openIfClosed.get() && ! isOpen()) return
204
202
205
- // If there is already queue of 2 renders we don't bother!
206
- if (queue.get() >= 2 ) return
203
+ // If we're already rendering we queue up another render!
204
+ if (paneMutex.isLocked) {
205
+ debouncedRender.set(true )
206
+ return
207
+ }
207
208
208
- // Await to acquire a semaphore before starting the render
209
- queue.incrementAndGet()
210
- semaphore.acquire()
209
+ // Await to acquire the mutex before we start rendering
210
+ paneMutex.lock()
211
211
try {
212
212
withTimeout(6 .seconds) {
213
213
pane = panes.collapse(backing.totalRows(), builder.fillMenuWithAir)
@@ -219,8 +219,12 @@ public abstract class AbstractInterfaceView<I : InterfacesInventory, T : Interfa
219
219
}
220
220
}
221
221
} finally {
222
- semaphore.release()
223
- queue.decrementAndGet()
222
+ paneMutex.unlock()
223
+ }
224
+
225
+ // If we queued up a debounced render we trigger another one!
226
+ if (debouncedRender.compareAndSet(true , false )) {
227
+ renderAndOpen()
224
228
}
225
229
}
226
230
@@ -279,9 +283,12 @@ public abstract class AbstractInterfaceView<I : InterfacesInventory, T : Interfa
279
283
val completedPane = pane.complete(player)
280
284
281
285
// Access to the pane has to be shared through a semaphore
282
- semaphore.acquire()
283
- panes[transform.priority] = completedPane
284
- semaphore.release()
286
+ paneMutex.lock()
287
+ try {
288
+ panes[transform.priority] = completedPane
289
+ } finally {
290
+ paneMutex.unlock()
291
+ }
285
292
}
286
293
287
294
protected open fun drawPaneToInventory (drawNormalInventory : Boolean , drawPlayerInventory : Boolean ) {
0 commit comments