62
62
using firebase::firestore::api::DocumentSnapshot;
63
63
using firebase::firestore::api::Settings;
64
64
using firebase::firestore::api::SnapshotMetadata;
65
+ using firebase::firestore::api::ThrowIllegalState;
65
66
using firebase::firestore::auth::CredentialsProvider;
66
67
using firebase::firestore::auth::User;
67
68
using firebase::firestore::core::DatabaseInfo;
@@ -128,7 +129,8 @@ @implementation FSTFirestoreClient {
128
129
std::unique_ptr<Executor> _userExecutor;
129
130
std::chrono::milliseconds _initialGcDelay;
130
131
std::chrono::milliseconds _regularGcDelay;
131
- BOOL _gcHasRun;
132
+ bool _gcHasRun;
133
+ std::atomic<bool > _isShutdown;
132
134
_Nullable id <FSTLRUDelegate> _lruDelegate;
133
135
DelayedOperation _lruCallback;
134
136
}
@@ -165,7 +167,8 @@ - (instancetype)initWithDatabaseInfo:(const DatabaseInfo &)databaseInfo
165
167
_credentialsProvider = credentialsProvider;
166
168
_userExecutor = std::move (userExecutor);
167
169
_workerQueue = std::move (workerQueue);
168
- _gcHasRun = NO ;
170
+ _gcHasRun = false ;
171
+ _isShutdown = false ;
169
172
_initialGcDelay = FSTLruGcInitialDelay;
170
173
_regularGcDelay = FSTLruGcRegularDelay;
171
174
@@ -270,7 +273,7 @@ - (void)scheduleLruGarbageCollection {
270
273
std::chrono::milliseconds delay = _gcHasRun ? _regularGcDelay : _initialGcDelay;
271
274
_lruCallback = _workerQueue->EnqueueAfterDelay (delay, TimerId::GarbageCollectionDelay, [self ]() {
272
275
[self ->_localStore collectGarbage: self ->_lruDelegate.gc];
273
- self->_gcHasRun = YES ;
276
+ self->_gcHasRun = true ;
274
277
[self scheduleLruGarbageCollection ];
275
278
});
276
279
}
@@ -283,6 +286,7 @@ - (void)credentialDidChangeWithUser:(const User &)user {
283
286
}
284
287
285
288
- (void )disableNetworkWithCallback : (util::StatusCallback)callback {
289
+ [self verifyNotShutdown ];
286
290
_workerQueue->Enqueue ([self , callback] {
287
291
_remoteStore->DisableNetwork ();
288
292
if (callback) {
@@ -292,6 +296,7 @@ - (void)disableNetworkWithCallback:(util::StatusCallback)callback {
292
296
}
293
297
294
298
- (void )enableNetworkWithCallback : (util::StatusCallback)callback {
299
+ [self verifyNotShutdown ];
295
300
_workerQueue->Enqueue ([self , callback] {
296
301
_remoteStore->EnableNetwork ();
297
302
if (callback) {
@@ -302,20 +307,29 @@ - (void)enableNetworkWithCallback:(util::StatusCallback)callback {
302
307
303
308
- (void )shutdownWithCallback : (util::StatusCallback)callback {
304
309
_workerQueue->Enqueue ([self , callback] {
305
- self->_credentialsProvider ->SetCredentialChangeListener (nullptr );
310
+ if (!_isShutdown) {
311
+ self->_credentialsProvider ->SetCredentialChangeListener (nullptr );
306
312
307
- // If we've scheduled LRU garbage collection, cancel it.
308
- if (self->_lruCallback ) {
309
- self->_lruCallback .Cancel ();
313
+ // If we've scheduled LRU garbage collection, cancel it.
314
+ if (self->_lruCallback ) {
315
+ self->_lruCallback .Cancel ();
316
+ }
317
+ _remoteStore->Shutdown ();
318
+ [self .persistence shutdown ];
319
+ self->_isShutdown = true ;
310
320
}
311
- _remoteStore->Shutdown ();
312
- [self .persistence shutdown ];
313
321
if (callback) {
314
322
self->_userExecutor ->Execute ([=] { callback (Status::OK ()); });
315
323
}
316
324
});
317
325
}
318
326
327
+ - (void )verifyNotShutdown {
328
+ if (_isShutdown) {
329
+ ThrowIllegalState (" The client has already been shutdown." );
330
+ }
331
+ }
332
+
319
333
- (std::shared_ptr<QueryListener>)listenToQuery : (FSTQuery *)query
320
334
options : (core::ListenOptions)options
321
335
listener : (ViewSnapshot::SharedListener &&)listener {
@@ -327,11 +341,13 @@ - (void)shutdownWithCallback:(util::StatusCallback)callback {
327
341
}
328
342
329
343
- (void )removeListener : (const std::shared_ptr<QueryListener> &)listener {
344
+ [self verifyNotShutdown ];
330
345
_workerQueue->Enqueue ([self , listener] { [self .eventManager removeListener: listener]; });
331
346
}
332
347
333
348
- (void )getDocumentFromLocalCache : (const DocumentReference &)doc
334
349
callback : (DocumentSnapshot::Listener &&)callback {
350
+ [self verifyNotShutdown ];
335
351
auto shared_callback = absl::ShareUniquePtr (std::move (callback));
336
352
_workerQueue->Enqueue ([self , doc, shared_callback] {
337
353
FSTMaybeDocument *maybeDoc = [self .localStore readDocument: doc.key ()];
@@ -362,6 +378,7 @@ - (void)getDocumentFromLocalCache:(const DocumentReference &)doc
362
378
- (void )getDocumentsFromLocalCache : (FIRQuery *)query
363
379
completion : (void (^)(FIRQuerySnapshot *_Nullable query,
364
380
NSError *_Nullable error))completion {
381
+ [self verifyNotShutdown ];
365
382
_workerQueue->Enqueue ([self , query, completion] {
366
383
DocumentMap docs = [self .localStore executeQuery: query.query];
367
384
@@ -391,6 +408,7 @@ - (void)writeMutations:(std::vector<FSTMutation *> &&)mutations
391
408
callback : (util::StatusCallback)callback {
392
409
// TODO(c++14): move `mutations` into lambda (C++14).
393
410
_workerQueue->Enqueue ([self , mutations, callback]() mutable {
411
+ [self verifyNotShutdown ];
394
412
if (mutations.empty ()) {
395
413
if (callback) {
396
414
self->_userExecutor ->Execute ([=] { callback (Status::OK ()); });
@@ -413,6 +431,7 @@ - (void)transactionWithRetries:(int)retries
413
431
resultCallback : (core::TransactionResultCallback)resultCallback {
414
432
// Dispatch the result back onto the user dispatch queue.
415
433
auto async_callback = [self , resultCallback](util::StatusOr<absl::any> maybe_value) {
434
+ [self verifyNotShutdown ];
416
435
if (resultCallback) {
417
436
self->_userExecutor ->Execute ([=] { resultCallback (std::move (maybe_value)); });
418
437
}
0 commit comments