[Android] Prevent concurrent access in renderers callbacks
Geoffrey Métais
git at videolan.org
Wed May 23 15:32:41 CEST 2018
vlc-android | branch: 3.0.x | Geoffrey Métais <geoffrey.metais at gmail.com> | Wed May 23 15:27:05 2018 +0200| [41e649a9955937406811339e79acd8276326f350] | committer: Geoffrey Métais
Prevent concurrent access in renderers callbacks
> https://code.videolan.org/videolan/vlc-android/commit/41e649a9955937406811339e79acd8276326f350
---
.../src/org/videolan/vlc/RendererDelegate.kt | 43 ++++++++++++++++------
1 file changed, 31 insertions(+), 12 deletions(-)
diff --git a/vlc-android/src/org/videolan/vlc/RendererDelegate.kt b/vlc-android/src/org/videolan/vlc/RendererDelegate.kt
index 5d295b036..0eeb789cd 100644
--- a/vlc-android/src/org/videolan/vlc/RendererDelegate.kt
+++ b/vlc-android/src/org/videolan/vlc/RendererDelegate.kt
@@ -22,6 +22,8 @@ package org.videolan.vlc
import kotlinx.coroutines.experimental.CoroutineStart
import kotlinx.coroutines.experimental.android.UI
import kotlinx.coroutines.experimental.async
+import kotlinx.coroutines.experimental.channels.Channel
+import kotlinx.coroutines.experimental.channels.actor
import kotlinx.coroutines.experimental.launch
import org.videolan.libvlc.RendererDiscoverer
import org.videolan.libvlc.RendererItem
@@ -34,8 +36,8 @@ object RendererDelegate : RendererDiscoverer.EventListener, ExternalMonitor.Netw
private val TAG = "VLC/RendererDelegate"
private val mDiscoverers = ArrayList<RendererDiscoverer>()
val renderers = ArrayList<RendererItem>()
- private val mListeners = LinkedList<RendererListener>()
- private val mPlayers = LinkedList<RendererPlayer>()
+ private val listeners = LinkedList<RendererListener>()
+ private val players = LinkedList<RendererPlayer>()
@Volatile private var started = false
var selectedRenderer: RendererItem? = null
@@ -65,13 +67,13 @@ object RendererDelegate : RendererDiscoverer.EventListener, ExternalMonitor.Netw
}
}
- suspend fun stop() {
+ fun stop() {
if (!started) return
started = false
for (discoverer in mDiscoverers) discoverer.stop()
clear()
onRenderersChanged()
- for (player in mPlayers) player.onRendererChanged(null)
+ cbActor.offer(RendererChanged(null))
}
private fun clear() {
@@ -93,20 +95,37 @@ object RendererDelegate : RendererDiscoverer.EventListener, ExternalMonitor.Netw
onRenderersChanged()
}
- fun addListener(listener: RendererListener) = mListeners.add(listener)
+ fun addListener(listener: RendererListener) = cbActor.offer(AddListener(listener))
- fun removeListener(listener: RendererListener) = mListeners.remove(listener)
+ fun removeListener(listener: RendererListener) = cbActor.offer(RemoveListener(listener))
- private fun onRenderersChanged() {
- for (listener in mListeners) listener.onRenderersChanged(renderers.isEmpty())
- }
+ private fun onRenderersChanged() = cbActor.offer(RenderersChanged())
fun selectRenderer(item: RendererItem?) {
selectedRenderer = item
- for (player in mPlayers) player.onRendererChanged(item)
+ cbActor.offer(RendererChanged(item))
}
- fun addPlayerListener(listener: RendererPlayer) = mPlayers.add(listener)
+ fun addPlayerListener(player: RendererPlayer) = cbActor.offer(AddPlayer(player))
+
+ fun removePlayerListener(player: RendererPlayer) = cbActor.offer(RemovePlayer(player))
- fun removePlayerListener(listener: RendererPlayer) = mPlayers.remove(listener)
+ private val cbActor = actor<CbAction>(UI, Channel.UNLIMITED) {
+ for (action in channel) when (action) {
+ is AddPlayer -> players.add(action.player)
+ is RemovePlayer -> players.remove(action.player)
+ is RendererChanged -> for (player in players) player.onRendererChanged(action.renderer)
+ is AddListener -> listeners.add(action.listener)
+ is RemoveListener -> listeners.remove(action.listener)
+ is RenderersChanged -> for (listener in listeners) listener.onRenderersChanged(renderers.isEmpty())
+ }
+ }
}
+
+sealed class CbAction
+private class AddPlayer(val player: RendererDelegate.RendererPlayer) : CbAction()
+private class RemovePlayer(val player: RendererDelegate.RendererPlayer) : CbAction()
+private class RendererChanged(val renderer: RendererItem?) : CbAction()
+private class AddListener(val listener: RendererDelegate.RendererListener) : CbAction()
+private class RemoveListener(val listener: RendererDelegate.RendererListener) : CbAction()
+private class RenderersChanged : CbAction()
More information about the Android
mailing list