Commit 7611dfd7 authored by Grisha Kruglov's avatar Grisha Kruglov
Browse files

Pre 2: remove unnecessary synchronization from FxaDeviceConstellation

I'm not sure it was ever necessary, to be honest. I think the way the 'refresh'
method is currently structured, simply marking internal 'constellationState'
as Volatile is enough - we're not concerned about concurrent access to it,
only about memory visibility across threads.

It's true that currently, work in this class happens on a pool thread,
so it's possible to have two racing 'refresh' methods running. Having one of them
loose the race and drop results on the floor should be just fine in this case.
parent 778a2052
......@@ -5,7 +5,6 @@
package mozilla.components.service.fxa
import android.content.Context
import androidx.annotation.GuardedBy
import androidx.lifecycle.LifecycleOwner
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Deferred
......@@ -39,12 +38,10 @@ class FxaDeviceConstellation(
private val deviceObserverRegistry = ObserverRegistry<DeviceConstellationObserver>()
@GuardedBy("this")
@Volatile
private var constellationState: ConstellationState? = null
override fun state(): ConstellationState? = synchronized(this) {
return constellationState
}
override fun state(): ConstellationState? = constellationState
override fun initDeviceAsync(
name: String,
......@@ -137,37 +134,35 @@ class FxaDeviceConstellation(
notifyObservers { onEvents(events) }
}
override fun refreshDevicesAsync(): Deferred<Boolean> = synchronized(this) {
return scope.async {
logger.info("Refreshing device list...")
override fun refreshDevicesAsync(): Deferred<Boolean> = scope.async {
logger.info("Refreshing device list...")
// Attempt to fetch devices, or bail out on failure.
val allDevices = fetchAllDevicesAsync().await() ?: return@async false
// Attempt to fetch devices, or bail out on failure.
val allDevices = fetchAllDevicesAsync().await() ?: return@async false
// Find the current device.
val currentDevice = allDevices.find { it.isCurrentDevice }
// Filter out the current devices.
val otherDevices = allDevices.filter { !it.isCurrentDevice }
// Find the current device.
val currentDevice = allDevices.find { it.isCurrentDevice }?.also {
// Check if our current device's push subscription needs to be renewed.
if (it.subscriptionExpired) {
logger.info("Current device needs push endpoint registration")
}
}
val newState = ConstellationState(currentDevice, otherDevices)
constellationState = newState
// Filter out the current devices.
val otherDevices = allDevices.filter { !it.isCurrentDevice }
CoroutineScope(Dispatchers.Main).launch {
// NB: at this point, 'constellationState' might have changed.
// Notify with an immutable, local 'newState' instead.
deviceObserverRegistry.notifyObservers { onDevicesUpdate(newState) }
}
val newState = ConstellationState(currentDevice, otherDevices)
constellationState = newState
// Check if our current device's push subscription needs to be renewed.
constellationState?.currentDevice?.let {
if (it.subscriptionExpired) {
logger.info("Current device needs push endpoint registration")
}
}
logger.info("Refreshed device list; saw ${allDevices.size} device(s).")
logger.info("Refreshed device list; saw ${allDevices.size} device(s).")
true
CoroutineScope(Dispatchers.Main).launch {
// NB: at this point, 'constellationState' might have changed.
// Notify with an immutable, local 'newState' instead.
deviceObserverRegistry.notifyObservers { onDevicesUpdate(newState) }
}
true
}
/**
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment