Switch from synchronized mutations to copy-on-write (#609)

## Description
Instead of synchronizing all access to event observers, use a
`CopyOnWriteArrayList`. This means sending events doesn't need to lock.
This commit is contained in:
Ray 2025-12-31 16:10:29 -05:00 committed by GitHub
parent 7e5a491d8e
commit 38697b011d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -24,6 +24,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SO
import android.content.Context import android.content.Context
import android.graphics.Bitmap import android.graphics.Bitmap
import android.view.Surface import android.view.Surface
import java.util.concurrent.CopyOnWriteArrayList
// Wrapper for native library // Wrapper for native library
@ -96,115 +97,93 @@ object MPVLib {
format: Int, format: Int,
) )
private val observers = mutableListOf<EventObserver>() private val observers = CopyOnWriteArrayList<EventObserver>()
@JvmStatic @JvmStatic
fun addObserver(o: EventObserver) { fun addObserver(o: EventObserver) {
synchronized(observers) {
observers.add(o) observers.add(o)
} }
}
@JvmStatic @JvmStatic
fun removeObserver(o: EventObserver) { fun removeObserver(o: EventObserver) {
synchronized(observers) {
observers.remove(o) observers.remove(o)
} }
}
@JvmStatic @JvmStatic
fun eventProperty( fun eventProperty(
property: String, property: String,
value: Long, value: Long,
) { ) {
synchronized(observers) {
for (o in observers) { for (o in observers) {
o.eventProperty(property, value) o.eventProperty(property, value)
} }
} }
}
@JvmStatic @JvmStatic
fun eventProperty( fun eventProperty(
property: String, property: String,
value: Boolean, value: Boolean,
) { ) {
synchronized(observers) {
for (o in observers) { for (o in observers) {
o.eventProperty(property, value) o.eventProperty(property, value)
} }
} }
}
@JvmStatic @JvmStatic
fun eventProperty( fun eventProperty(
property: String, property: String,
value: Double, value: Double,
) { ) {
synchronized(observers) {
for (o in observers) { for (o in observers) {
o.eventProperty(property, value) o.eventProperty(property, value)
} }
} }
}
@JvmStatic @JvmStatic
fun eventProperty( fun eventProperty(
property: String, property: String,
value: String, value: String,
) { ) {
synchronized(observers) {
for (o in observers) { for (o in observers) {
o.eventProperty(property, value) o.eventProperty(property, value)
} }
} }
}
@JvmStatic @JvmStatic
fun eventProperty(property: String) { fun eventProperty(property: String) {
synchronized(observers) {
for (o in observers) { for (o in observers) {
o.eventProperty(property) o.eventProperty(property)
} }
} }
}
@JvmStatic @JvmStatic
fun event(eventId: Int) { fun event(eventId: Int) {
synchronized(observers) {
for (o in observers) { for (o in observers) {
o.event(eventId) o.event(eventId)
} }
} }
}
@JvmStatic @JvmStatic
fun eventEndFile( fun eventEndFile(
reason: Int, reason: Int,
error: Int, error: Int,
) { ) {
synchronized(observers) {
for (o in observers) { for (o in observers) {
o.eventEndFile(reason, error) o.eventEndFile(reason, error)
} }
} }
}
private val log_observers = mutableListOf<LogObserver>() private val log_observers = CopyOnWriteArrayList<LogObserver>()
@JvmStatic @JvmStatic
fun addLogObserver(o: LogObserver) { fun addLogObserver(o: LogObserver) {
synchronized(log_observers) {
log_observers.add(o) log_observers.add(o)
} }
}
@JvmStatic @JvmStatic
fun removeLogObserver(o: LogObserver) { fun removeLogObserver(o: LogObserver) {
synchronized(log_observers) {
log_observers.remove(o) log_observers.remove(o)
} }
}
@JvmStatic @JvmStatic
fun logMessage( fun logMessage(
@ -212,12 +191,10 @@ object MPVLib {
level: Int, level: Int,
text: String, text: String,
) { ) {
synchronized(log_observers) {
for (o in log_observers) { for (o in log_observers) {
o.logMessage(prefix, level, text) o.logMessage(prefix, level, text)
} }
} }
}
interface EventObserver { interface EventObserver {
fun eventProperty(property: String) fun eventProperty(property: String)