@@ -47,6 +47,7 @@ import kotlinx.coroutines.ensureActive
47
47
import kotlinx.coroutines.flow.MutableStateFlow
48
48
import kotlinx.coroutines.flow.filter
49
49
import kotlinx.coroutines.flow.first
50
+ import kotlinx.coroutines.flow.getAndUpdate
50
51
import kotlinx.coroutines.launch
51
52
52
53
/* * Base class that shares logic for managing the Auth token and AppCheck token. */
@@ -148,9 +149,18 @@ internal sealed class DataConnectCredentialsTokenManager<T : Any>(
148
149
*/
149
150
fun close () {
150
151
logger.debug { " close()" }
152
+
151
153
weakThis.clear()
152
154
coroutineScope.cancel()
153
- setClosedState()
155
+
156
+ val oldState = state.getAndUpdate { State .Closed }
157
+ when (oldState) {
158
+ is State .Closed -> {}
159
+ is State .New -> {}
160
+ is State .StateWithProvider -> {
161
+ removeTokenListener(oldState.provider)
162
+ }
163
+ }
154
164
}
155
165
156
166
/* *
@@ -175,51 +185,41 @@ internal sealed class DataConnectCredentialsTokenManager<T : Any>(
175
185
logger.debug { " awaitTokenProvider() done: currentState=$currentState " }
176
186
}
177
187
178
- // This function must ONLY be called from close().
179
- private fun setClosedState () {
180
- while (true ) {
181
- val oldState = state.value
182
- val provider: T ? =
183
- when (oldState) {
184
- is State .Closed -> return
185
- is State .New -> null
186
- is State .Idle -> oldState.provider
187
- is State .Active -> oldState.provider
188
- }
189
-
190
- if (state.compareAndSet(oldState, State .Closed )) {
191
- provider?.let { removeTokenListener(it) }
192
- break
193
- }
194
- }
195
- }
196
-
197
188
/* *
198
189
* Sets a flag to force-refresh the token upon the next call to [getToken].
199
190
*
200
191
* If [close] has been called, this method does nothing.
201
192
*/
202
193
fun forceRefresh () {
203
194
logger.debug { " forceRefresh()" }
204
- while (true ) {
205
- val oldState = state.value
206
- val newState: State .StateWithForceTokenRefresh <T > =
207
- when (oldState) {
208
- is State .Closed -> return
209
- is State .New -> oldState.copy(forceTokenRefresh = true )
210
- is State .Idle -> oldState.copy(forceTokenRefresh = true )
211
- is State .Active -> {
212
- val message = " needs token refresh (wgrwbrvjxt)"
213
- oldState.job.cancel(message, ForceRefresh (message))
214
- State .Idle (oldState.provider, forceTokenRefresh = true )
195
+ val oldState =
196
+ state.getAndUpdate { currentState ->
197
+ val newState =
198
+ when (currentState) {
199
+ is State .Closed -> State .Closed
200
+ is State .New -> currentState.copy(forceTokenRefresh = true )
201
+ is State .Idle -> currentState.copy(forceTokenRefresh = true )
202
+ is State .Active -> State .Idle (currentState.provider, forceTokenRefresh = true )
215
203
}
204
+
205
+ check(newState is State .Closed || newState is State .StateWithForceTokenRefresh <T >) {
206
+ " internal error gbazc7qr66: newState should have been Closed or " +
207
+ " StateWithForceTokenRefresh, but got: $newState "
208
+ }
209
+ check((newState as ? State .StateWithForceTokenRefresh <T >)?.forceTokenRefresh != = false ) {
210
+ " internal error fnzwyrsez2: newState.forceTokenRefresh should have been true"
216
211
}
217
212
218
- check(newState.forceTokenRefresh) {
219
- " newState.forceTokenRefresh should be true (error code gnvr2wx7nz)"
213
+ newState
220
214
}
221
- if (state.compareAndSet(oldState, newState)) {
222
- break
215
+
216
+ when (oldState) {
217
+ is State .Closed -> {}
218
+ is State .New -> {}
219
+ is State .Idle -> {}
220
+ is State .Active -> {
221
+ val message = " needs token refresh (wgrwbrvjxt)"
222
+ oldState.job.cancel(message, ForceRefresh (message))
223
223
}
224
224
}
225
225
}
@@ -350,30 +350,30 @@ internal sealed class DataConnectCredentialsTokenManager<T : Any>(
350
350
logger.debug { " onProviderAvailable(newProvider=$newProvider )" }
351
351
addTokenListener(newProvider)
352
352
353
- while (true ) {
354
- val oldState = state.value
355
- val newState =
356
- when (oldState) {
357
- is State .Closed -> {
358
- logger.debug {
359
- " onProviderAvailable(newProvider=$newProvider )" +
360
- " unregistering token listener that was just added"
361
- }
362
- removeTokenListener(newProvider)
363
- break
364
- }
365
- is State .New -> State .Idle (newProvider, oldState.forceTokenRefresh)
366
- is State .Idle -> State .Idle (newProvider, oldState.forceTokenRefresh)
367
- is State .Active -> {
368
- val newProviderClassName = newProvider::class .qualifiedName
369
- val message = " a new provider $newProviderClassName is available (symhxtmazy)"
370
- oldState.job.cancel(message, NewProvider (message))
371
- State .Idle (newProvider, forceTokenRefresh = false )
372
- }
353
+ val oldState =
354
+ state.getAndUpdate { currentState ->
355
+ when (currentState) {
356
+ is State .Closed -> State .Closed
357
+ is State .New -> State .Idle (newProvider, currentState.forceTokenRefresh)
358
+ is State .Idle -> State .Idle (newProvider, currentState.forceTokenRefresh)
359
+ is State .Active -> State .Idle (newProvider, forceTokenRefresh = false )
373
360
}
361
+ }
374
362
375
- if (state.compareAndSet(oldState, newState)) {
376
- break
363
+ when (oldState) {
364
+ is State .Closed -> {
365
+ logger.debug {
366
+ " onProviderAvailable(newProvider=$newProvider )" +
367
+ " unregistering token listener that was just added"
368
+ }
369
+ removeTokenListener(newProvider)
370
+ }
371
+ is State .New -> {}
372
+ is State .Idle -> {}
373
+ is State .Active -> {
374
+ val newProviderClassName = newProvider::class .qualifiedName
375
+ val message = " a new provider $newProviderClassName is available (symhxtmazy)"
376
+ oldState.job.cancel(message, NewProvider (message))
377
377
}
378
378
}
379
379
}
0 commit comments