diff --git a/Firestore/Example/Firestore.xcodeproj/project.pbxproj b/Firestore/Example/Firestore.xcodeproj/project.pbxproj index 733ddf41f6c..b228b8707a1 100644 --- a/Firestore/Example/Firestore.xcodeproj/project.pbxproj +++ b/Firestore/Example/Firestore.xcodeproj/project.pbxproj @@ -175,7 +175,6 @@ 6EDD3B6020BF25AE00C33877 /* FSTFuzzTestsPrincipal.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6EDD3B5E20BF24D000C33877 /* FSTFuzzTestsPrincipal.mm */; }; 6F3CAC76D918D6B0917EDF92 /* query_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B9C261C26C5D311E1E3C0CB9 /* query_test.cc */; }; 71719F9F1E33DC2100824A3D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 71719F9D1E33DC2100824A3D /* LaunchScreen.storyboard */; }; - 7346E61D20325C6900FD6CEF /* FSTDispatchQueueTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7346E61C20325C6900FD6CEF /* FSTDispatchQueueTests.mm */; }; 73866AA12082B0A5009BB4FF /* FIRArrayTransformTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 73866A9F2082B069009BB4FF /* FIRArrayTransformTests.mm */; }; 73FE5066020EF9B2892C86BF /* hard_assert_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 444B7AB3F5A2929070CB1363 /* hard_assert_test.cc */; }; 84DBE646DCB49305879D3500 /* nanopb_string_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 353EEE078EF3F39A9B7279F6 /* nanopb_string_test.cc */; }; @@ -308,7 +307,7 @@ 2A0CF41BA5AED6049B0BEB2C /* type_traits_apple_test.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; path = type_traits_apple_test.mm; sourceTree = ""; }; 2B50B3A0DF77100EEE887891 /* Pods_Firestore_Tests_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_Tests_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 332485C4DCC6BA0DBB5E31B7 /* leveldb_util_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = leveldb_util_test.cc; sourceTree = ""; }; - 353EEE078EF3F39A9B7279F6 /* nanopb_string_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = nanopb_string_test.cc; path = nanopb/nanopb_string_test.cc; sourceTree = ""; }; + 353EEE078EF3F39A9B7279F6 /* nanopb_string_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = nanopb_string_test.cc; path = nanopb/nanopb_string_test.cc; sourceTree = ""; }; 358C3B5FE573B1D60A4F7592 /* strerror_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = strerror_test.cc; sourceTree = ""; }; 3B843E4A1F3930A400548890 /* remote_store_spec_test.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = remote_store_spec_test.json; sourceTree = ""; }; 3C81DE3772628FE297055662 /* Pods-Firestore_Example_iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Example_iOS.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Firestore_Example_iOS/Pods-Firestore_Example_iOS.debug.xcconfig"; sourceTree = ""; }; @@ -488,7 +487,6 @@ 6EDD3B5C20BF247500C33877 /* Firestore_FuzzTests_iOS-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Firestore_FuzzTests_iOS-Info.plist"; sourceTree = ""; }; 6EDD3B5E20BF24D000C33877 /* FSTFuzzTestsPrincipal.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FSTFuzzTestsPrincipal.mm; sourceTree = ""; }; 71719F9E1E33DC2100824A3D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - 7346E61C20325C6900FD6CEF /* FSTDispatchQueueTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FSTDispatchQueueTests.mm; sourceTree = ""; }; 73866A9F2082B069009BB4FF /* FIRArrayTransformTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FIRArrayTransformTests.mm; sourceTree = ""; }; 79507DF8378D3C42F5B36268 /* string_win_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = string_win_test.cc; sourceTree = ""; }; 84434E57CA72951015FC71BC /* Pods-Firestore_FuzzTests_iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_FuzzTests_iOS.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Firestore_FuzzTests_iOS/Pods-Firestore_FuzzTests_iOS.debug.xcconfig"; sourceTree = ""; }; @@ -526,6 +524,7 @@ B67BF448216EB43000CA9097 /* create_noop_connectivity_monitor.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = create_noop_connectivity_monitor.cc; sourceTree = ""; }; B686F2AD2023DDB20028D6BE /* field_path_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = field_path_test.cc; sourceTree = ""; }; B686F2B02024FFD70028D6BE /* resource_path_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = resource_path_test.cc; sourceTree = ""; }; + B69CF05A219B9105004C434D /* FIRFirestore+Testing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "FIRFirestore+Testing.h"; sourceTree = ""; }; B6BBE42F21262CF400C6A53E /* grpc_stream_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = grpc_stream_test.cc; sourceTree = ""; }; B6D1B68420E2AB1A00B35856 /* exponential_backoff_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = exponential_backoff_test.cc; sourceTree = ""; }; B6D9649021544D4F00EB9CFB /* grpc_connection_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = grpc_connection_test.cc; sourceTree = ""; }; @@ -1161,7 +1160,7 @@ DE51B1851F0D48AC0013853F /* Util */ = { isa = PBXGroup; children = ( - 7346E61C20325C6900FD6CEF /* FSTDispatchQueueTests.mm */, + B69CF05A219B9105004C434D /* FIRFirestore+Testing.h */, 54E9281C1F33950B00C1953E /* FSTEventAccumulator.h */, 5492E0392021401F00B64F25 /* FSTEventAccumulator.mm */, DE51B1881F0D48AC0013853F /* FSTHelpers.h */, @@ -1878,7 +1877,6 @@ 5492E058202154AB00B64F25 /* FSTAPIHelpers.mm in Sources */, DE2EF0851F3D0B6E003D0CDC /* FSTArraySortedDictionaryTests.m in Sources */, 5492E0C82021557E00B64F25 /* FSTDatastoreTests.mm in Sources */, - 7346E61D20325C6900FD6CEF /* FSTDispatchQueueTests.mm in Sources */, 5492E0B92021555100B64F25 /* FSTDocumentKeyTests.mm in Sources */, 5492E0BA2021555100B64F25 /* FSTDocumentSetTests.mm in Sources */, 5492E0BD2021555100B64F25 /* FSTDocumentTests.mm in Sources */, diff --git a/Firestore/Example/Tests/API/FSTAPIHelpers.mm b/Firestore/Example/Tests/API/FSTAPIHelpers.mm index 4a43b4b138b..5e5c41314de 100644 --- a/Firestore/Example/Tests/API/FSTAPIHelpers.mm +++ b/Firestore/Example/Tests/API/FSTAPIHelpers.mm @@ -53,7 +53,7 @@ database:"abc" persistenceKey:@"db123" credentialsProvider:nil - workerDispatchQueue:nil + workerQueue:nil firebaseApp:nil]; }); #pragma clang diagnostic pop diff --git a/Firestore/Example/Tests/Core/FSTEventManagerTests.mm b/Firestore/Example/Tests/Core/FSTEventManagerTests.mm index b5a784c24d3..e8f5955c3f1 100644 --- a/Firestore/Example/Tests/Core/FSTEventManagerTests.mm +++ b/Firestore/Example/Tests/Core/FSTEventManagerTests.mm @@ -22,7 +22,6 @@ #import "Firestore/Source/Core/FSTQuery.h" #import "Firestore/Source/Core/FSTSyncEngine.h" #import "Firestore/Source/Model/FSTDocumentSet.h" -#import "Firestore/Source/Util/FSTDispatchQueue.h" #import "Firestore/Example/Tests/Util/FSTHelpers.h" @@ -49,13 +48,7 @@ @interface FSTEventManager () @interface FSTEventManagerTests : XCTestCase @end -@implementation FSTEventManagerTests { - FSTDispatchQueue *_testUserQueue; -} - -- (void)setUp { - _testUserQueue = [FSTDispatchQueue queueWith:dispatch_get_main_queue()]; -} +@implementation FSTEventManagerTests - (FSTQueryListener *)noopListenerForQuery:(FSTQuery *)query { return [[FSTQueryListener alloc] diff --git a/Firestore/Example/Tests/Core/FSTQueryListenerTests.mm b/Firestore/Example/Tests/Core/FSTQueryListenerTests.mm index 4d46757daaf..ed2aa0bd1db 100644 --- a/Firestore/Example/Tests/Core/FSTQueryListenerTests.mm +++ b/Firestore/Example/Tests/Core/FSTQueryListenerTests.mm @@ -33,7 +33,7 @@ using firebase::firestore::model::DocumentKeySet; using firebase::firestore::model::OnlineState; -using firebase::firestore::util::internal::ExecutorLibdispatch; +using firebase::firestore::util::ExecutorLibdispatch; NS_ASSUME_NONNULL_BEGIN diff --git a/Firestore/Example/Tests/Integration/API/FIRDatabaseTests.mm b/Firestore/Example/Tests/Integration/API/FIRDatabaseTests.mm index f69dca510b5..6e0873a4e20 100644 --- a/Firestore/Example/Tests/Integration/API/FIRDatabaseTests.mm +++ b/Firestore/Example/Tests/Integration/API/FIRDatabaseTests.mm @@ -22,7 +22,8 @@ #import "Firestore/Example/Tests/Util/FSTIntegrationTestCase.h" #import "Firestore/Source/API/FIRFirestore+Internal.h" #import "Firestore/Source/Core/FSTFirestoreClient.h" -#import "Firestore/Source/Util/FSTDispatchQueue.h" + +using firebase::firestore::util::TimerId; @interface FIRDatabaseTests : FSTIntegrationTestCase @end @@ -1204,7 +1205,7 @@ - (void)testWriteStreamReconnectsAfterIdle { FIRFirestore *firestore = doc.firestore; [self writeDocumentRef:doc data:@{@"foo" : @"bar"}]; - [[self queueForFirestore:firestore] runDelayedCallbacksUntil:FSTTimerIDWriteStreamIdle]; + [self queueForFirestore:firestore] -> RunScheduledOperationsUntil(TimerId::WriteStreamIdle); [self writeDocumentRef:doc data:@{@"foo" : @"bar"}]; } @@ -1213,7 +1214,7 @@ - (void)testWatchStreamReconnectsAfterIdle { FIRFirestore *firestore = doc.firestore; [self readSnapshotForRef:[self documentRef] requireOnline:YES]; - [[self queueForFirestore:firestore] runDelayedCallbacksUntil:FSTTimerIDListenStreamIdle]; + [self queueForFirestore:firestore] -> RunScheduledOperationsUntil(TimerId::ListenStreamIdle); [self readSnapshotForRef:[self documentRef] requireOnline:YES]; } diff --git a/Firestore/Example/Tests/Integration/FSTDatastoreTests.mm b/Firestore/Example/Tests/Integration/FSTDatastoreTests.mm index e931e185277..b0140bb6b76 100644 --- a/Firestore/Example/Tests/Integration/FSTDatastoreTests.mm +++ b/Firestore/Example/Tests/Integration/FSTDatastoreTests.mm @@ -19,6 +19,8 @@ #import #import +#include + #import "Firestore/Source/API/FIRDocumentReference+Internal.h" #import "Firestore/Source/API/FSTUserDataConverter.h" #import "Firestore/Source/Core/FSTFirestoreClient.h" @@ -31,7 +33,6 @@ #import "Firestore/Source/Remote/FSTDatastore.h" #import "Firestore/Source/Remote/FSTRemoteEvent.h" #import "Firestore/Source/Remote/FSTRemoteStore.h" -#import "Firestore/Source/Util/FSTDispatchQueue.h" #import "Firestore/Example/Tests/Util/FSTIntegrationTestCase.h" @@ -39,8 +40,11 @@ #include "Firestore/core/src/firebase/firestore/core/database_info.h" #include "Firestore/core/src/firebase/firestore/model/database_id.h" #include "Firestore/core/src/firebase/firestore/model/precondition.h" +#include "Firestore/core/src/firebase/firestore/util/async_queue.h" +#include "Firestore/core/src/firebase/firestore/util/executor_libdispatch.h" #include "Firestore/core/src/firebase/firestore/util/hard_assert.h" #include "Firestore/core/src/firebase/firestore/util/string_apple.h" +#include "absl/memory/memory.h" namespace util = firebase::firestore::util; using firebase::firestore::auth::EmptyCredentialsProvider; @@ -51,6 +55,8 @@ using firebase::firestore::model::Precondition; using firebase::firestore::model::TargetId; using firebase::firestore::remote::GrpcConnection; +using firebase::firestore::util::AsyncQueue; +using firebase::firestore::util::ExecutorLibdispatch; NS_ASSUME_NONNULL_BEGIN @@ -146,7 +152,7 @@ @interface FSTDatastoreTests : XCTestCase @end @implementation FSTDatastoreTests { - FSTDispatchQueue *_testWorkerQueue; + std::unique_ptr _testWorkerQueue; FSTLocalStore *_localStore; EmptyCredentialsProvider _credentials; @@ -169,29 +175,26 @@ - (void)setUp { _databaseInfo = DatabaseInfo(database_id, "test-key", util::MakeString(settings.host), settings.sslEnabled); - _testWorkerQueue = [FSTDispatchQueue - queueWith:dispatch_queue_create("com.google.firestore.FSTDatastoreTestsWorkerQueue", - DISPATCH_QUEUE_SERIAL)]; - + dispatch_queue_t queue = dispatch_queue_create( + "com.google.firestore.FSTDatastoreTestsWorkerQueue", DISPATCH_QUEUE_SERIAL); + _testWorkerQueue = absl::make_unique(absl::make_unique(queue)); _datastore = [FSTDatastore datastoreWithDatabase:&_databaseInfo - workerDispatchQueue:_testWorkerQueue + workerQueue:_testWorkerQueue.get() credentials:&_credentials]; _remoteStore = [[FSTRemoteStore alloc] initWithLocalStore:_localStore datastore:_datastore - workerDispatchQueue:_testWorkerQueue]; + workerQueue:_testWorkerQueue.get()]; - [_testWorkerQueue dispatchAsync:^() { - [_remoteStore start]; - }]; + _testWorkerQueue->Enqueue([=] { [_remoteStore start]; }); } - (void)tearDown { XCTestExpectation *completion = [self expectationWithDescription:@"shutdown"]; - [_testWorkerQueue dispatchAsync:^{ + _testWorkerQueue->Enqueue([=] { [_remoteStore shutdown]; [completion fulfill]; - }]; + }); [self awaitExpectations]; [super tearDown]; @@ -219,12 +222,12 @@ - (void)testStreamingWrite { FSTMutationBatch *batch = [[FSTMutationBatch alloc] initWithBatchID:23 localWriteTime:[FIRTimestamp timestamp] mutations:@[ mutation ]]; - [_testWorkerQueue dispatchAsync:^{ + _testWorkerQueue->Enqueue([=] { [_remoteStore addBatchToWritePipeline:batch]; // The added batch won't be written immediately because write stream wasn't yet open -- // trigger its opening. [_remoteStore fillWritePipeline]; - }]; + }); [self awaitExpectations]; } diff --git a/Firestore/Example/Tests/SpecTests/FSTMockDatastore.mm b/Firestore/Example/Tests/SpecTests/FSTMockDatastore.mm index 440117519cd..2b84bdcd6df 100644 --- a/Firestore/Example/Tests/SpecTests/FSTMockDatastore.mm +++ b/Firestore/Example/Tests/SpecTests/FSTMockDatastore.mm @@ -26,7 +26,6 @@ #import "Firestore/Source/Model/FSTMutation.h" #import "Firestore/Source/Remote/FSTSerializerBeta.h" #import "Firestore/Source/Remote/FSTStream.h" -#import "Firestore/Source/Util/FSTDispatchQueue.h" #import "Firestore/Example/Tests/Remote/FSTWatchChange+Testing.h" @@ -37,6 +36,7 @@ #include "Firestore/core/src/firebase/firestore/remote/connectivity_monitor.h" #include "Firestore/core/src/firebase/firestore/remote/grpc_connection.h" #include "Firestore/core/src/firebase/firestore/remote/stream.h" +#include "Firestore/core/src/firebase/firestore/util/async_queue.h" #include "Firestore/core/src/firebase/firestore/util/log.h" #include "Firestore/core/src/firebase/firestore/util/string_apple.h" #include "Firestore/core/test/firebase/firestore/util/create_noop_connectivity_monitor.h" @@ -249,12 +249,13 @@ int sent_mutations_count() const { @interface FSTMockDatastore () /** Properties implemented in FSTDatastore that are nonpublic. */ -@property(nonatomic, strong, readonly) FSTDispatchQueue *workerDispatchQueue; @property(nonatomic, assign, readonly) CredentialsProvider *credentials; @end @implementation FSTMockDatastore { + AsyncQueue *_workerQueue; + std::shared_ptr _watchStream; std::shared_ptr _writeStream; @@ -266,24 +267,23 @@ @implementation FSTMockDatastore { #pragma mark - Overridden FSTDatastore methods. - (instancetype)initWithDatabaseInfo:(const DatabaseInfo *)databaseInfo - workerDispatchQueue:(FSTDispatchQueue *)workerDispatchQueue + workerQueue:(AsyncQueue *)workerQueue credentials:(CredentialsProvider *)credentials { if (self = [super initWithDatabaseInfo:databaseInfo - workerDispatchQueue:workerDispatchQueue + workerQueue:workerQueue credentials:credentials]) { - _workerDispatchQueue = workerDispatchQueue; + _workerQueue = workerQueue; _credentials = credentials; _connectivityMonitor = CreateNoOpConnectivityMonitor(); - _grpcConnection = - absl::make_unique(*databaseInfo, [workerDispatchQueue implementation], - &_grpcQueue, _connectivityMonitor.get()); + _grpcConnection = absl::make_unique(*databaseInfo, workerQueue, &_grpcQueue, + _connectivityMonitor.get()); } return self; } - (std::shared_ptr)createWatchStreamWithDelegate:(id)delegate { _watchStream = std::make_shared( - [self.workerDispatchQueue implementation], self.credentials, + _workerQueue, self.credentials, [[FSTSerializerBeta alloc] initWithDatabaseID:&self.databaseInfo->database_id()], _grpcConnection.get(), delegate, self); @@ -292,7 +292,7 @@ - (instancetype)initWithDatabaseInfo:(const DatabaseInfo *)databaseInfo - (std::shared_ptr)createWriteStreamWithDelegate:(id)delegate { _writeStream = std::make_shared( - [self.workerDispatchQueue implementation], self.credentials, + _workerQueue, self.credentials, [[FSTSerializerBeta alloc] initWithDatabaseID:&self.databaseInfo->database_id()], _grpcConnection.get(), delegate, self); diff --git a/Firestore/Example/Tests/SpecTests/FSTSpecTests.mm b/Firestore/Example/Tests/SpecTests/FSTSpecTests.mm index 9f246b76a59..a95d5c3e84d 100644 --- a/Firestore/Example/Tests/SpecTests/FSTSpecTests.mm +++ b/Firestore/Example/Tests/SpecTests/FSTSpecTests.mm @@ -32,7 +32,6 @@ #import "Firestore/Source/Remote/FSTExistenceFilter.h" #import "Firestore/Source/Remote/FSTWatchChange.h" #import "Firestore/Source/Util/FSTClasses.h" -#import "Firestore/Source/Util/FSTDispatchQueue.h" #import "Firestore/Example/Tests/Remote/FSTWatchChange+Testing.h" #import "Firestore/Example/Tests/SpecTests/FSTSyncEngineTestDriver.h" @@ -41,6 +40,7 @@ #include "Firestore/core/src/firebase/firestore/auth/user.h" #include "Firestore/core/src/firebase/firestore/model/document_key.h" #include "Firestore/core/src/firebase/firestore/model/snapshot_version.h" +#include "Firestore/core/src/firebase/firestore/util/async_queue.h" #include "Firestore/core/src/firebase/firestore/util/hard_assert.h" #include "Firestore/core/src/firebase/firestore/util/log.h" #include "Firestore/core/src/firebase/firestore/util/string_apple.h" @@ -52,6 +52,7 @@ using firebase::firestore::model::DocumentKey; using firebase::firestore::model::SnapshotVersion; using firebase::firestore::model::TargetId; +using firebase::firestore::util::TimerId; NS_ASSUME_NONNULL_BEGIN @@ -373,19 +374,19 @@ - (void)doDrainQueue { } - (void)doRunTimer:(NSString *)timer { - FSTTimerID timerID; + TimerId timerID; if ([timer isEqualToString:@"all"]) { - timerID = FSTTimerIDAll; + timerID = TimerId::All; } else if ([timer isEqualToString:@"listen_stream_idle"]) { - timerID = FSTTimerIDListenStreamIdle; + timerID = TimerId::ListenStreamIdle; } else if ([timer isEqualToString:@"listen_stream_connection_backoff"]) { - timerID = FSTTimerIDListenStreamConnectionBackoff; + timerID = TimerId::ListenStreamConnectionBackoff; } else if ([timer isEqualToString:@"write_stream_idle"]) { - timerID = FSTTimerIDWriteStreamIdle; + timerID = TimerId::WriteStreamIdle; } else if ([timer isEqualToString:@"write_stream_connection_backoff"]) { - timerID = FSTTimerIDWriteStreamConnectionBackoff; + timerID = TimerId::WriteStreamConnectionBackoff; } else if ([timer isEqualToString:@"online_state_timeout"]) { - timerID = FSTTimerIDOnlineStateTimeout; + timerID = TimerId::OnlineStateTimeout; } else { HARD_FAIL("runTimer spec step specified unknown timer: %s", timer); } diff --git a/Firestore/Example/Tests/SpecTests/FSTSyncEngineTestDriver.h b/Firestore/Example/Tests/SpecTests/FSTSyncEngineTestDriver.h index 9d08a32c8ae..548947aa23e 100644 --- a/Firestore/Example/Tests/SpecTests/FSTSyncEngineTestDriver.h +++ b/Firestore/Example/Tests/SpecTests/FSTSyncEngineTestDriver.h @@ -20,12 +20,12 @@ #include #import "Firestore/Source/Remote/FSTRemoteStore.h" -#import "Firestore/Source/Util/FSTDispatchQueue.h" #include "Firestore/core/src/firebase/firestore/auth/user.h" #include "Firestore/core/src/firebase/firestore/model/document_key.h" #include "Firestore/core/src/firebase/firestore/model/snapshot_version.h" #include "Firestore/core/src/firebase/firestore/model/types.h" +#include "Firestore/core/src/firebase/firestore/util/async_queue.h" @class FSTDocumentKey; @class FSTMutation; @@ -227,9 +227,9 @@ typedef std::unordered_map #include +#include #include #import "Firestore/Source/Core/FSTEventManager.h" @@ -38,8 +39,11 @@ #include "Firestore/core/src/firebase/firestore/core/database_info.h" #include "Firestore/core/src/firebase/firestore/model/database_id.h" #include "Firestore/core/src/firebase/firestore/model/document_key.h" +#include "Firestore/core/src/firebase/firestore/util/async_queue.h" +#include "Firestore/core/src/firebase/firestore/util/executor_libdispatch.h" #include "Firestore/core/src/firebase/firestore/util/hard_assert.h" #include "Firestore/core/src/firebase/firestore/util/log.h" +#include "absl/memory/memory.h" using firebase::firestore::auth::EmptyCredentialsProvider; using firebase::firestore::auth::HashUser; @@ -50,6 +54,9 @@ using firebase::firestore::model::OnlineState; using firebase::firestore::model::SnapshotVersion; using firebase::firestore::model::TargetId; +using firebase::firestore::util::AsyncQueue; +using firebase::firestore::util::TimerId; +using firebase::firestore::util::ExecutorLibdispatch; NS_ASSUME_NONNULL_BEGIN @@ -75,7 +82,6 @@ @interface FSTSyncEngineTestDriver () @property(nonatomic, strong, readonly) FSTRemoteStore *remoteStore; @property(nonatomic, strong, readonly) FSTLocalStore *localStore; @property(nonatomic, strong, readonly) FSTSyncEngine *syncEngine; -@property(nonatomic, strong, readonly) FSTDispatchQueue *dispatchQueue; @property(nonatomic, strong, readonly) id persistence; #pragma mark - Data structures for holding events sent by the watch stream. @@ -98,6 +104,8 @@ @interface FSTSyncEngineTestDriver () @end @implementation FSTSyncEngineTestDriver { + std::unique_ptr _workerQueue; + // ivar is declared as mutable. std::unordered_map *, HashUser> _outstandingWrites; @@ -128,16 +136,16 @@ - (instancetype)initWithPersistence:(id)persistence // Set up the sync engine and various stores. dispatch_queue_t queue = dispatch_queue_create("sync_engine_test_driver", DISPATCH_QUEUE_SERIAL); - _dispatchQueue = [FSTDispatchQueue queueWith:queue]; + _workerQueue = absl::make_unique(absl::make_unique(queue)); _persistence = persistence; _localStore = [[FSTLocalStore alloc] initWithPersistence:persistence initialUser:initialUser]; _datastore = [[FSTMockDatastore alloc] initWithDatabaseInfo:&_databaseInfo - workerDispatchQueue:_dispatchQueue + workerQueue:_workerQueue.get() credentials:&_credentialProvider]; _remoteStore = [[FSTRemoteStore alloc] initWithLocalStore:_localStore datastore:_datastore - workerDispatchQueue:_dispatchQueue]; + workerQueue:_workerQueue.get()]; _syncEngine = [[FSTSyncEngine alloc] initWithLocalStore:_localStore remoteStore:_remoteStore @@ -174,8 +182,7 @@ - (instancetype)initWithPersistence:(id)persistence } - (void)drainQueue { - [_dispatchQueue dispatchSync:^(){ - }]; + _workerQueue->EnqueueBlocking([] {}); } - (const User &)currentUser { @@ -188,10 +195,10 @@ - (void)applyChangedOnlineState:(OnlineState)onlineState { } - (void)start { - [self.dispatchQueue dispatchSync:^{ + _workerQueue->EnqueueBlocking([&] { [self.localStore start]; [self.remoteStore start]; - }]; + }); } - (void)validateUsage { @@ -202,10 +209,10 @@ - (void)validateUsage { } - (void)shutdown { - [self.dispatchQueue dispatchSync:^{ + _workerQueue->EnqueueBlocking([&] { [self.remoteStore shutdown]; [self.persistence shutdown]; - }]; + }); } - (void)validateNextWriteSent:(FSTMutation *)expectedWrite { @@ -232,29 +239,25 @@ - (int)watchStreamRequestCount { } - (void)disableNetwork { - [self.dispatchQueue dispatchSync:^{ + _workerQueue->EnqueueBlocking([&] { // Make sure to execute all writes that are currently queued. This allows us // to assert on the total number of requests sent before shutdown. [self.remoteStore fillWritePipeline]; [self.remoteStore disableNetwork]; - }]; + }); } - (void)enableNetwork { - [self.dispatchQueue dispatchSync:^{ - [self.remoteStore enableNetwork]; - }]; + _workerQueue->EnqueueBlocking([&] { [self.remoteStore enableNetwork]; }); } -- (void)runTimer:(FSTTimerID)timerID { - [self.dispatchQueue runDelayedCallbacksUntil:timerID]; +- (void)runTimer:(TimerId)timerID { + _workerQueue->RunScheduledOperationsUntil(timerID); } - (void)changeUser:(const User &)user { _currentUser = user; - [self.dispatchQueue dispatchSync:^{ - [self.syncEngine credentialDidChangeWithUser:user]; - }]; + _workerQueue->EnqueueBlocking([&] { [self.syncEngine credentialDidChangeWithUser:user]; }); } - (FSTOutstandingWrite *)receiveWriteAckWithVersion:(const SnapshotVersion &)commitVersion @@ -264,9 +267,8 @@ - (FSTOutstandingWrite *)receiveWriteAckWithVersion:(const SnapshotVersion &)com [[self currentOutstandingWrites] removeObjectAtIndex:0]; [self validateNextWriteSent:write.write]; - [self.dispatchQueue dispatchSync:^{ - [self.datastore ackWriteWithVersion:commitVersion mutationResults:mutationResults]; - }]; + _workerQueue->EnqueueBlocking( + [&] { [self.datastore ackWriteWithVersion:commitVersion mutationResults:mutationResults]; }); return write; } @@ -287,9 +289,7 @@ - (FSTOutstandingWrite *)receiveWriteError:(int)errorCode } LOG_DEBUG("Failing a write."); - [self.dispatchQueue dispatchSync:^{ - [self.datastore failWriteWithError:error]; - }]; + _workerQueue->EnqueueBlocking([&] { [self.datastore failWriteWithError:error]; }); return write; } @@ -329,19 +329,15 @@ - (TargetId)addUserListenerWithQuery:(FSTQuery *)query { [self.events addObject:event]; }]; self.queryListeners[query] = listener; - __block TargetId targetID; - [self.dispatchQueue dispatchSync:^{ - targetID = [self.eventManager addListener:listener]; - }]; + TargetId targetID; + _workerQueue->EnqueueBlocking([&] { targetID = [self.eventManager addListener:listener]; }); return targetID; } - (void)removeUserListenerWithQuery:(FSTQuery *)query { FSTQueryListener *listener = self.queryListeners[query]; [self.queryListeners removeObjectForKey:query]; - [self.dispatchQueue dispatchSync:^{ - [self.eventManager removeListener:listener]; - }]; + _workerQueue->EnqueueBlocking([&] { [self.eventManager removeListener:listener]; }); } - (void)writeUserMutation:(FSTMutation *)mutation { @@ -349,7 +345,7 @@ - (void)writeUserMutation:(FSTMutation *)mutation { write.write = mutation; [[self currentOutstandingWrites] addObject:write]; LOG_DEBUG("sending a user write."); - [self.dispatchQueue dispatchSync:^{ + _workerQueue->EnqueueBlocking([=] { [self.syncEngine writeMutations:@[ mutation ] completion:^(NSError *_Nullable error) { LOG_DEBUG("A callback was called with error: %s", error); @@ -365,27 +361,26 @@ - (void)writeUserMutation:(FSTMutation *)mutation { [self.acknowledgedDocs addObject:mutationKey]; } }]; - }]; + }); } - (void)receiveWatchChange:(FSTWatchChange *)change snapshotVersion:(const SnapshotVersion &)snapshot { - [self.dispatchQueue dispatchSync:^{ - [self.datastore writeWatchChange:change snapshotVersion:snapshot]; - }]; + _workerQueue->EnqueueBlocking( + [&] { [self.datastore writeWatchChange:change snapshotVersion:snapshot]; }); } - (void)receiveWatchStreamError:(int)errorCode userInfo:(NSDictionary *)userInfo { NSError *error = [NSError errorWithDomain:FIRFirestoreErrorDomain code:errorCode userInfo:userInfo]; - [self.dispatchQueue dispatchSync:^{ + _workerQueue->EnqueueBlocking([&] { [self.datastore failWatchStreamWithError:error]; // Unlike web, stream should re-open synchronously (if we have any listeners) if (self.queryListeners.count > 0) { HARD_ASSERT(self.datastore.isWatchStreamOpen, "Watch stream is open"); } - }]; + }); } - (std::map)currentLimboDocuments { diff --git a/Firestore/Example/Tests/Util/FIRFirestore+Testing.h b/Firestore/Example/Tests/Util/FIRFirestore+Testing.h new file mode 100644 index 00000000000..cf75738e865 --- /dev/null +++ b/Firestore/Example/Tests/Util/FIRFirestore+Testing.h @@ -0,0 +1,31 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +#include "Firestore/core/src/firebase/firestore/util/async_queue.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRFirestore (Testing) + +- (firebase::firestore::util::AsyncQueue*)workerQueue; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Firestore/Example/Tests/Util/FSTDispatchQueueTests.mm b/Firestore/Example/Tests/Util/FSTDispatchQueueTests.mm deleted file mode 100644 index 1f49aa4d7d9..00000000000 --- a/Firestore/Example/Tests/Util/FSTDispatchQueueTests.mm +++ /dev/null @@ -1,276 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import "Firestore/Source/Util/FSTDispatchQueue.h" - -#import - -#import "Firestore/Example/Tests/Util/XCTestCase+Await.h" - -// In these generic tests the specific TimerIDs don't matter. -static const FSTTimerID timerID1 = FSTTimerIDListenStreamConnectionBackoff; -static const FSTTimerID timerID2 = FSTTimerIDListenStreamIdle; -static const FSTTimerID timerID3 = FSTTimerIDWriteStreamConnectionBackoff; - -@interface FSTDispatchQueueTests : XCTestCase -@end - -@implementation FSTDispatchQueueTests { - dispatch_queue_t _underlyingQueue; - FSTDispatchQueue *_queue; - NSMutableArray *_completedSteps; - NSArray *_expectedSteps; - XCTestExpectation *_expectation; -} - -- (void)setUp { - [super setUp]; - _underlyingQueue = dispatch_queue_create("FSTDispatchQueueTests", DISPATCH_QUEUE_SERIAL); - _queue = [[FSTDispatchQueue alloc] initWithQueue:_underlyingQueue]; - _completedSteps = [NSMutableArray array]; - _expectedSteps = nil; -} - -- (void)testDispatchAsyncBlocksSubmissionFromTasksOnTheQueue { - XCTestExpectation *expectation = [self expectationWithDescription:@"completion"]; - __block NSException *caught = nil; - __block NSString *problem = nil; - - [_queue dispatchAsync:^{ - @try { - [self->_queue dispatchAsync:^{ - }]; - problem = @"Should have disallowed submission into the queue while running"; - [expectation fulfill]; - } @catch (NSException *ex) { - caught = ex; - [expectation fulfill]; - } - }]; - - [self awaitExpectations]; - XCTAssertNil(problem); - XCTAssertNotNil(caught); - - XCTAssertEqualObjects(caught.name, NSInternalInconsistencyException); - XCTAssertTrue([caught.reason - hasPrefix: - @"FIRESTORE INTERNAL ASSERTION FAILED: " - @"Enqueue methods cannot be called when we are already running on target executor"]); -} - -- (void)testDispatchAsyncAllowingSameQueueActuallyAllowsSameQueue { - XCTestExpectation *expectation = [self expectationWithDescription:@"completion"]; - __block NSException *caught = nil; - - [_queue dispatchAsync:^{ - @try { - [self->_queue dispatchAsyncAllowingSameQueue:^{ - [expectation fulfill]; - }]; - } @catch (NSException *ex) { - caught = ex; - [expectation fulfill]; - } - }]; - - [self awaitExpectations]; - XCTAssertNil(caught); -} - -- (void)testDispatchAsyncAllowsSameQueueForUnownedActions { - XCTestExpectation *expectation = [self expectationWithDescription:@"completion"]; - __block NSException *caught = nil; - - // Simulate the case of an action that runs on our queue because e.g. it's run by a user-owned - // deinitializer that happened to be last held in one of our API methods. - dispatch_async(_underlyingQueue, ^{ - @try { - [self->_queue dispatchAsync:^{ - [expectation fulfill]; - }]; - } @catch (NSException *ex) { - caught = ex; - [expectation fulfill]; - } - }); - - [self awaitExpectations]; - XCTAssertNil(caught); -} - -- (void)testDispatchSyncBlocksSubmissionFromTasksOnTheQueue { - XCTestExpectation *expectation = [self expectationWithDescription:@"completion"]; - __block NSException *caught = nil; - __block NSString *problem = nil; - - [_queue dispatchSync:^{ - @try { - [self->_queue dispatchSync:^{ - }]; - problem = @"Should have disallowed submission into the queue while running"; - [expectation fulfill]; - } @catch (NSException *ex) { - caught = ex; - [expectation fulfill]; - } - }]; - - [self awaitExpectations]; - XCTAssertNil(problem); - XCTAssertNotNil(caught); - - XCTAssertEqualObjects(caught.name, NSInternalInconsistencyException); - XCTAssertTrue([caught.reason - hasPrefix: - @"FIRESTORE INTERNAL ASSERTION FAILED: " - @"Enqueue methods cannot be called when we are already running on target executor"]); -} - -- (void)testVerifyIsCurrentQueueActuallyRequiresCurrentQueue { - XCTAssertNotEqualObjects(_underlyingQueue, dispatch_get_main_queue()); - - __block NSException *caught = nil; - @try { - // Run on the main queue not the FSTDispatchQueue's queue - [_queue verifyIsCurrentQueue]; - } @catch (NSException *ex) { - caught = ex; - } - XCTAssertNotNil(caught); - XCTAssertTrue([caught.reason hasPrefix:@"FIRESTORE INTERNAL ASSERTION FAILED: " - @"Expected to be called by the executor " - @"associated with this queue"]); -} - -- (void)testVerifyIsCurrentQueueRequiresOperationIsInProgress { - __block NSException *caught = nil; - dispatch_sync(_underlyingQueue, ^{ - @try { - [self->_queue verifyIsCurrentQueue]; - } @catch (NSException *ex) { - caught = ex; - } - }); - XCTAssertNotNil(caught); - XCTAssertTrue( - [caught.reason hasPrefix:@"FIRESTORE INTERNAL ASSERTION FAILED: " - @"VerifyIsCurrentQueue called when no operation is executing"]); -} - -- (void)testVerifyIsCurrentQueueWorksWithOperationIsInProgress { - __block NSException *caught = nil; - [_queue dispatchSync:^{ - @try { - [self->_queue verifyIsCurrentQueue]; - } @catch (NSException *ex) { - caught = ex; - } - }]; - XCTAssertNil(caught); -} - -- (void)testEnterCheckedOperationDisallowsNesting { - __block NSException *caught = nil; - __block NSString *problem = nil; - [_queue dispatchSync:^{ - @try { - [self->_queue enterCheckedOperation:^{ - }]; - problem = @"Should not have been able to enter nested enterCheckedOperation"; - } @catch (NSException *ex) { - caught = ex; - } - }]; - XCTAssertNil(problem); - XCTAssertNotNil(caught); - XCTAssertTrue( - [caught.reason hasPrefix:@"FIRESTORE INTERNAL ASSERTION FAILED: " - @"ExecuteBlocking may not be called before the previous operation " - @"finishes executing"]); -} - -/** - * Helper to return a block that adds @(n) to _completedSteps when run and fulfils _expectation if - * the _completedSteps match the _expectedSteps. - */ -- (void (^)())blockForStep:(int)n { - return ^void() { - [self->_completedSteps addObject:@(n)]; - if (self->_expectedSteps && self->_completedSteps.count >= self->_expectedSteps.count) { - XCTAssertEqualObjects(self->_completedSteps, self->_expectedSteps); - [self->_expectation fulfill]; - } - }; -} - -- (void)testCanScheduleCallbacksInTheFuture { - _expectation = [self expectationWithDescription:@"Expected steps"]; - _expectedSteps = @[ @1, @2, @3, @4 ]; - [_queue dispatchAsync:[self blockForStep:1]]; - [_queue dispatchAsync:^{ - [_queue dispatchAfterDelay:0.005 timerID:timerID1 block:[self blockForStep:4]]; - [_queue dispatchAfterDelay:0.001 timerID:timerID2 block:[self blockForStep:3]]; - }]; - [_queue dispatchAsync:[self blockForStep:2]]; - - [self awaitExpectations]; -} - -- (void)testCanCancelDelayedCallbacks { - _expectation = [self expectationWithDescription:@"Expected steps"]; - _expectedSteps = @[ @1, @3 ]; - // Queue everything from the queue to ensure nothing completes before we cancel. - [_queue dispatchAsync:^{ - [self->_queue dispatchAsyncAllowingSameQueue:[self blockForStep:1]]; - FSTDelayedCallback *step2Timer = - [self->_queue dispatchAfterDelay:.001 timerID:timerID1 block:[self blockForStep:2]]; - [self->_queue dispatchAfterDelay:.005 timerID:timerID2 block:[self blockForStep:3]]; - - XCTAssertTrue([self->_queue containsDelayedCallbackWithTimerID:timerID1]); - [step2Timer cancel]; - XCTAssertFalse([self->_queue containsDelayedCallbackWithTimerID:timerID1]); - }]; - - [self awaitExpectations]; -} - -- (void)testCanManuallyDrainAllDelayedCallbacksForTesting { - [_queue dispatchAsync:[self blockForStep:1]]; - [_queue dispatchAsync:^{ - [_queue dispatchAfterDelay:20 timerID:timerID1 block:[self blockForStep:4]]; - [_queue dispatchAfterDelay:10 timerID:timerID2 block:[self blockForStep:3]]; - }]; - [_queue dispatchAsync:[self blockForStep:2]]; - - [_queue runDelayedCallbacksUntil:FSTTimerIDAll]; - XCTAssertEqualObjects(_completedSteps, (@[ @1, @2, @3, @4 ])); -} - -- (void)testCanManuallyDrainSpecificDelayedCallbacksForTesting { - [_queue dispatchAsync:[self blockForStep:1]]; - [_queue dispatchAsync:^{ - [_queue dispatchAfterDelay:20 timerID:timerID1 block:[self blockForStep:5]]; - [_queue dispatchAfterDelay:10 timerID:timerID2 block:[self blockForStep:3]]; - [_queue dispatchAfterDelay:15 timerID:timerID3 block:[self blockForStep:4]]; - }]; - [_queue dispatchAsync:[self blockForStep:2]]; - - [_queue runDelayedCallbacksUntil:timerID3]; - XCTAssertEqualObjects(_completedSteps, (@[ @1, @2, @3, @4 ])); -} - -@end diff --git a/Firestore/Example/Tests/Util/FSTIntegrationTestCase.h b/Firestore/Example/Tests/Util/FSTIntegrationTestCase.h index 53fd5961d34..f1b938fd051 100644 --- a/Firestore/Example/Tests/Util/FSTIntegrationTestCase.h +++ b/Firestore/Example/Tests/Util/FSTIntegrationTestCase.h @@ -21,6 +21,8 @@ #import "FIRFirestoreSource.h" +#include "Firestore/core/src/firebase/firestore/util/async_queue.h" + @class FIRCollectionReference; @class FIRDocumentSnapshot; @class FIRDocumentReference; @@ -29,7 +31,6 @@ @class FIRFirestoreSettings; @class FIRQuery; @class FSTEventAccumulator; -@class FSTDispatchQueue; NS_ASSUME_NONNULL_BEGIN @@ -98,7 +99,7 @@ extern "C" { - (void)enableNetwork; -- (FSTDispatchQueue *)queueForFirestore:(FIRFirestore *)firestore; +- (firebase::firestore::util::AsyncQueue *)queueForFirestore:(FIRFirestore *)firestore; /** * "Blocks" the current thread/run loop until the block returns YES. diff --git a/Firestore/Example/Tests/Util/FSTIntegrationTestCase.mm b/Firestore/Example/Tests/Util/FSTIntegrationTestCase.mm index e1b06e686e1..0d42a11bf19 100644 --- a/Firestore/Example/Tests/Util/FSTIntegrationTestCase.mm +++ b/Firestore/Example/Tests/Util/FSTIntegrationTestCase.mm @@ -47,19 +47,24 @@ #import "Firestore/Source/API/FIRFirestore+Internal.h" #import "Firestore/Source/Core/FSTFirestoreClient.h" #import "Firestore/Source/Local/FSTLevelDB.h" -#import "Firestore/Source/Util/FSTDispatchQueue.h" +#import "Firestore/Example/Tests/Util/FIRFirestore+Testing.h" #import "Firestore/Example/Tests/Util/FSTEventAccumulator.h" +#include "Firestore/core/src/firebase/firestore/util/async_queue.h" +#include "Firestore/core/src/firebase/firestore/util/executor_libdispatch.h" + namespace util = firebase::firestore::util; using firebase::firestore::auth::CredentialsProvider; using firebase::firestore::auth::EmptyCredentialsProvider; using firebase::firestore::model::DatabaseId; using firebase::firestore::testutil::AppForUnitTesting; using firebase::firestore::remote::GrpcConnection; +using firebase::firestore::util::AsyncQueue; using firebase::firestore::util::CreateAutoId; using firebase::firestore::util::Path; using firebase::firestore::util::Status; +using firebase::firestore::util::ExecutorLibdispatch; NS_ASSUME_NONNULL_BEGIN @@ -69,10 +74,6 @@ */ static const double kPrimingTimeout = 45.0; -@interface FIRFirestore (Testing) -@property(nonatomic, strong) FSTDispatchQueue *workerDispatchQueue; -@end - static NSString *defaultProjectId; static FIRFirestoreSettings *defaultSettings; @@ -181,8 +182,10 @@ + (FIRFirestoreSettings *)settings { - (FIRFirestore *)firestoreWithProjectID:(NSString *)projectID { NSString *persistenceKey = [NSString stringWithFormat:@"db%lu", (unsigned long)_firestores.count]; - FSTDispatchQueue *workerDispatchQueue = [FSTDispatchQueue - queueWith:dispatch_queue_create("com.google.firebase.firestore", DISPATCH_QUEUE_SERIAL)]; + dispatch_queue_t queue = + dispatch_queue_create("com.google.firebase.firestore", DISPATCH_QUEUE_SERIAL); + std::unique_ptr workerQueue = + absl::make_unique(absl::make_unique(queue)); FIRSetLoggerLevel(FIRLoggerLevelDebug); @@ -194,7 +197,7 @@ - (FIRFirestore *)firestoreWithProjectID:(NSString *)projectID { database:DatabaseId::kDefault persistenceKey:persistenceKey credentialsProvider:std::move(credentials_provider) - workerDispatchQueue:workerDispatchQueue + workerQueue:std::move(workerQueue) firebaseApp:app]; firestore.settings = [FSTIntegrationTestCase settings]; @@ -403,8 +406,8 @@ - (void)enableNetwork { [self awaitExpectations]; } -- (FSTDispatchQueue *)queueForFirestore:(FIRFirestore *)firestore { - return firestore.workerDispatchQueue; +- (AsyncQueue *)queueForFirestore:(FIRFirestore *)firestore { + return [firestore workerQueue]; } - (void)waitUntil:(BOOL (^)())predicate { diff --git a/Firestore/Source/API/FIRFirestore+Internal.h b/Firestore/Source/API/FIRFirestore+Internal.h index 3e2ecaffefc..0878237316a 100644 --- a/Firestore/Source/API/FIRFirestore+Internal.h +++ b/Firestore/Source/API/FIRFirestore+Internal.h @@ -21,11 +21,11 @@ #include "Firestore/core/src/firebase/firestore/auth/credentials_provider.h" #include "Firestore/core/src/firebase/firestore/model/database_id.h" +#include "Firestore/core/src/firebase/firestore/util/async_queue.h" #include "absl/strings/string_view.h" NS_ASSUME_NONNULL_BEGIN -@class FSTDispatchQueue; @class FSTFirestoreClient; @class FSTUserDataConverter; @@ -35,13 +35,14 @@ NS_ASSUME_NONNULL_BEGIN * Initializes a Firestore object with all the required parameters directly. This exists so that * tests can create FIRFirestore objects without needing FIRApp. */ -- (instancetype)initWithProjectID:(std::string)projectID - database:(std::string)database - persistenceKey:(NSString *)persistenceKey - credentialsProvider:(std::unique_ptr) - credentialsProvider - workerDispatchQueue:(FSTDispatchQueue *)workerDispatchQueue - firebaseApp:(FIRApp *)app; +- (instancetype) + initWithProjectID:(std::string)projectID + database:(std::string)database + persistenceKey:(NSString *)persistenceKey + credentialsProvider: + (std::unique_ptr)credentialsProvider + workerQueue:(std::unique_ptr)workerQueue + firebaseApp:(FIRApp *)app; @end @@ -60,6 +61,8 @@ NS_ASSUME_NONNULL_BEGIN - (void)shutdownWithCompletion:(nullable void (^)(NSError *_Nullable error))completion NS_SWIFT_NAME(shutdown(completion:)); +- (firebase::firestore::util::AsyncQueue *)workerQueue; + // FIRFirestore ownes the DatabaseId instance. @property(nonatomic, assign, readonly) const firebase::firestore::model::DatabaseId *databaseID; @property(nonatomic, strong, readonly) FSTFirestoreClient *client; diff --git a/Firestore/Source/API/FIRFirestore.mm b/Firestore/Source/API/FIRFirestore.mm index 3f33f877bb9..6fac8a4536a 100644 --- a/Firestore/Source/API/FIRFirestore.mm +++ b/Firestore/Source/API/FIRFirestore.mm @@ -35,7 +35,6 @@ #import "Firestore/Source/API/FSTFirestoreComponent.h" #import "Firestore/Source/API/FSTUserDataConverter.h" #import "Firestore/Source/Core/FSTFirestoreClient.h" -#import "Firestore/Source/Util/FSTDispatchQueue.h" #import "Firestore/Source/Util/FSTUsageValidation.h" #include "Firestore/core/src/firebase/firestore/auth/credentials_provider.h" @@ -43,21 +42,22 @@ #include "Firestore/core/src/firebase/firestore/core/database_info.h" #include "Firestore/core/src/firebase/firestore/model/database_id.h" #include "Firestore/core/src/firebase/firestore/model/resource_path.h" +#include "Firestore/core/src/firebase/firestore/util/async_queue.h" +#include "Firestore/core/src/firebase/firestore/util/executor_libdispatch.h" #include "Firestore/core/src/firebase/firestore/util/hard_assert.h" #include "Firestore/core/src/firebase/firestore/util/log.h" #include "Firestore/core/src/firebase/firestore/util/string_apple.h" #include "absl/memory/memory.h" -#include "Firestore/core/src/firebase/firestore/util/executor_libdispatch.h" - namespace util = firebase::firestore::util; using firebase::firestore::auth::CredentialsProvider; using firebase::firestore::auth::FirebaseCredentialsProvider; using firebase::firestore::core::DatabaseInfo; using firebase::firestore::model::DatabaseId; using firebase::firestore::model::ResourcePath; -using util::internal::Executor; -using util::internal::ExecutorLibdispatch; +using util::AsyncQueue; +using util::Executor; +using util::ExecutorLibdispatch; NS_ASSUME_NONNULL_BEGIN @@ -72,7 +72,6 @@ @interface FIRFirestore () { } @property(nonatomic, strong) NSString *persistenceKey; -@property(nonatomic, strong) FSTDispatchQueue *workerDispatchQueue; // Note that `client` is updated after initialization, but marking this readwrite would generate an // incorrect setter (since we make the assignment to `client` inside an `@synchronized` block. @@ -82,11 +81,18 @@ @interface FIRFirestore () { @end @implementation FIRFirestore { + // Ownership will be transferred to `FSTFirestoreClient` as soon as the client is created. + std::unique_ptr _workerQueue; + // All guarded by @synchronized(self) FIRFirestoreSettings *_settings; FSTFirestoreClient *_client; } +- (AsyncQueue *)workerQueue { + return [_client workerQueue]; +} + + (NSMutableDictionary *)instances { static dispatch_once_t token = 0; static NSMutableDictionary *instances; @@ -163,7 +169,7 @@ - (instancetype)initWithProjectID:(std::string)projectID database:(std::string)database persistenceKey:(NSString *)persistenceKey credentialsProvider:(std::unique_ptr)credentialsProvider - workerDispatchQueue:(FSTDispatchQueue *)workerDispatchQueue + workerQueue:(std::unique_ptr)workerQueue firebaseApp:(FIRApp *)app { if (self = [super init]) { _databaseID = DatabaseId{std::move(projectID), std::move(database)}; @@ -180,7 +186,7 @@ - (instancetype)initWithProjectID:(std::string)projectID [[FSTUserDataConverter alloc] initWithDatabaseID:&_databaseID preConverter:block]; _persistenceKey = persistenceKey; _credentialsProvider = std::move(credentialsProvider); - _workerDispatchQueue = workerDispatchQueue; + _workerQueue = std::move(workerQueue); _app = app; _settings = [[FIRFirestoreSettings alloc] init]; } @@ -257,11 +263,12 @@ const DatabaseInfo database_info(*self.databaseID, util::MakeString(_persistence std::unique_ptr userExecutor = absl::make_unique(_settings.dispatchQueue); + HARD_ASSERT(_workerQueue, "Expected non-null _workerQueue"); _client = [FSTFirestoreClient clientWithDatabaseInfo:database_info usePersistence:_settings.persistenceEnabled credentialsProvider:_credentialsProvider.get() userExecutor:std::move(userExecutor) - workerDispatchQueue:_workerDispatchQueue]; + workerQueue:std::move(_workerQueue)]; } } } @@ -344,18 +351,14 @@ - (void)runTransactionWithBlock:(id _Nullable (^)(FIRTransaction *, NSError **er } - (void)shutdownWithCompletion:(nullable void (^)(NSError *_Nullable error))completion { - FSTFirestoreClient *client; - @synchronized(self) { - client = _client; - _client = nil; - } - - if (!client) { - // We should be dispatching the callback on the user dispatch queue but if the client is nil - // here that queue was never created. - completion(nil); + if (!_client) { + if (completion) { + // We should be dispatching the callback on the user dispatch queue but if the client is nil + // here that queue was never created. + completion(nil); + } } else { - [client shutdownWithCompletion:completion]; + [_client shutdownWithCompletion:completion]; } } diff --git a/Firestore/Source/API/FSTFirestoreComponent.mm b/Firestore/Source/API/FSTFirestoreComponent.mm index 5a429ea57b7..61c3c4c2800 100644 --- a/Firestore/Source/API/FSTFirestoreComponent.mm +++ b/Firestore/Source/API/FSTFirestoreComponent.mm @@ -29,16 +29,19 @@ #include #import "Firestore/Source/API/FIRFirestore+Internal.h" -#import "Firestore/Source/Util/FSTDispatchQueue.h" #import "Firestore/Source/Util/FSTUsageValidation.h" #include "Firestore/core/src/firebase/firestore/auth/credentials_provider.h" #include "Firestore/core/src/firebase/firestore/auth/firebase_credentials_provider_apple.h" +#include "Firestore/core/src/firebase/firestore/util/async_queue.h" +#include "Firestore/core/src/firebase/firestore/util/executor_libdispatch.h" #include "Firestore/core/src/firebase/firestore/util/hard_assert.h" #include "absl/memory/memory.h" namespace util = firebase::firestore::util; using firebase::firestore::auth::CredentialsProvider; using firebase::firestore::auth::FirebaseCredentialsProvider; +using util::AsyncQueue; +using util::ExecutorLibdispatch; NS_ASSUME_NONNULL_BEGIN @@ -80,8 +83,10 @@ - (FIRFirestore *)firestoreForDatabase:(NSString *)database { if (!self.app.isDefaultApp) { absl::StrAppend(&queue_name, ".", util::MakeString(self.app.name)); } - FSTDispatchQueue *workerDispatchQueue = [FSTDispatchQueue - queueWith:dispatch_queue_create(queue_name.c_str(), DISPATCH_QUEUE_SERIAL)]; + + auto executor = absl::make_unique( + dispatch_queue_create(queue_name.c_str(), DISPATCH_QUEUE_SERIAL)); + auto workerQueue = absl::make_unique(std::move(executor)); id auth = FIR_COMPONENT(FIRAuthInterop, self.app.container); std::unique_ptr credentials_provider = @@ -93,7 +98,7 @@ - (FIRFirestore *)firestoreForDatabase:(NSString *)database { database:util::MakeString(database) persistenceKey:persistenceKey credentialsProvider:std::move(credentials_provider) - workerDispatchQueue:workerDispatchQueue + workerQueue:std::move(workerQueue) firebaseApp:self.app]; _instances[key] = firestore; } diff --git a/Firestore/Source/Core/FSTFirestoreClient.h b/Firestore/Source/Core/FSTFirestoreClient.h index 0f38e96bb85..f8314f32afa 100644 --- a/Firestore/Source/Core/FSTFirestoreClient.h +++ b/Firestore/Source/Core/FSTFirestoreClient.h @@ -25,6 +25,7 @@ #include "Firestore/core/src/firebase/firestore/auth/credentials_provider.h" #include "Firestore/core/src/firebase/firestore/core/database_info.h" #include "Firestore/core/src/firebase/firestore/model/database_id.h" +#include "Firestore/core/src/firebase/firestore/util/async_queue.h" #include "Firestore/core/src/firebase/firestore/util/executor.h" @class FIRDocumentReference; @@ -33,7 +34,6 @@ @class FIRQuerySnapshot; @class FSTDatabaseID; @class FSTDatabaseInfo; -@class FSTDispatchQueue; @class FSTDocument; @class FSTListenOptions; @class FSTMutation; @@ -55,14 +55,13 @@ NS_ASSUME_NONNULL_BEGIN * * All callbacks and events will be triggered on the provided userExecutor. */ -+ (instancetype)clientWithDatabaseInfo:(const firebase::firestore::core::DatabaseInfo &)databaseInfo - usePersistence:(BOOL)usePersistence - credentialsProvider:(firebase::firestore::auth::CredentialsProvider *) - credentialsProvider // no passing ownership - userExecutor: - (std::unique_ptr) - userExecutor - workerDispatchQueue:(FSTDispatchQueue *)workerDispatchQueue; ++ (instancetype) + clientWithDatabaseInfo:(const firebase::firestore::core::DatabaseInfo &)databaseInfo + usePersistence:(BOOL)usePersistence + credentialsProvider:(firebase::firestore::auth::CredentialsProvider *) + credentialsProvider // no passing ownership + userExecutor:(std::unique_ptr)userExecutor + workerQueue:(std::unique_ptr)workerQueue; - (instancetype)init __attribute__((unavailable("Use static constructor method."))); @@ -116,7 +115,10 @@ NS_ASSUME_NONNULL_BEGIN * Dispatch queue for user callbacks / events. This will often be the "Main Dispatch Queue" of the * app but the developer can configure it to a different queue if they so choose. */ -- (firebase::firestore::util::internal::Executor *)userExecutor; +- (firebase::firestore::util::Executor *)userExecutor; + +/** For testing only. */ +- (firebase::firestore::util::AsyncQueue *)workerQueue; @end diff --git a/Firestore/Source/Core/FSTFirestoreClient.mm b/Firestore/Source/Core/FSTFirestoreClient.mm index ae147c46abb..e82cae926b7 100644 --- a/Firestore/Source/Core/FSTFirestoreClient.mm +++ b/Firestore/Source/Core/FSTFirestoreClient.mm @@ -41,11 +41,11 @@ #import "Firestore/Source/Remote/FSTRemoteStore.h" #import "Firestore/Source/Remote/FSTSerializerBeta.h" #import "Firestore/Source/Util/FSTClasses.h" -#import "Firestore/Source/Util/FSTDispatchQueue.h" #include "Firestore/core/src/firebase/firestore/auth/credentials_provider.h" #include "Firestore/core/src/firebase/firestore/core/database_info.h" #include "Firestore/core/src/firebase/firestore/model/database_id.h" +#include "Firestore/core/src/firebase/firestore/util/async_queue.h" #include "Firestore/core/src/firebase/firestore/util/hard_assert.h" #include "Firestore/core/src/firebase/firestore/util/log.h" #include "Firestore/core/src/firebase/firestore/util/string_apple.h" @@ -59,7 +59,8 @@ using firebase::firestore::model::OnlineState; using firebase::firestore::util::Path; using firebase::firestore::util::Status; -using firebase::firestore::util::internal::Executor; +using firebase::firestore::util::AsyncQueue; +using firebase::firestore::util::Executor; NS_ASSUME_NONNULL_BEGIN @@ -72,7 +73,7 @@ - (instancetype)initWithDatabaseInfo:(const DatabaseInfo &)databaseInfo credentialsProvider: (CredentialsProvider *)credentialsProvider // no passing ownership userExecutor:(std::unique_ptr)userExecutor - workerDispatchQueue:(FSTDispatchQueue *)queue NS_DESIGNATED_INITIALIZER; + workerQueue:(std::unique_ptr)queue NS_DESIGNATED_INITIALIZER; @property(nonatomic, assign, readonly) const DatabaseInfo *databaseInfo; @property(nonatomic, strong, readonly) FSTEventManager *eventManager; @@ -81,20 +82,20 @@ - (instancetype)initWithDatabaseInfo:(const DatabaseInfo &)databaseInfo @property(nonatomic, strong, readonly) FSTRemoteStore *remoteStore; @property(nonatomic, strong, readonly) FSTLocalStore *localStore; -/** - * Dispatch queue responsible for all of our internal processing. When we get incoming work from - * the user (via public API) or the network (incoming GRPC messages), we should always dispatch - * onto this queue. This ensures our internal data structures are never accessed from multiple - * threads simultaneously. - */ -@property(nonatomic, strong, readonly) FSTDispatchQueue *workerDispatchQueue; - // Does not own the CredentialsProvider instance. @property(nonatomic, assign, readonly) CredentialsProvider *credentialsProvider; @end @implementation FSTFirestoreClient { + /** + * Async queue responsible for all of our internal processing. When we get incoming work from + * the user (via public API) or the network (incoming gRPC messages), we should always dispatch + * onto this queue. This ensures our internal data structures are never accessed from multiple + * threads simultaneously. + */ + std::unique_ptr _workerQueue; + std::unique_ptr _userExecutor; } @@ -102,17 +103,21 @@ - (Executor *)userExecutor { return _userExecutor.get(); } +- (AsyncQueue *)workerQueue { + return _workerQueue.get(); +} + + (instancetype)clientWithDatabaseInfo:(const DatabaseInfo &)databaseInfo usePersistence:(BOOL)usePersistence credentialsProvider: (CredentialsProvider *)credentialsProvider // no passing ownership userExecutor:(std::unique_ptr)userExecutor - workerDispatchQueue:(FSTDispatchQueue *)workerDispatchQueue { + workerQueue:(std::unique_ptr)workerQueue { return [[FSTFirestoreClient alloc] initWithDatabaseInfo:databaseInfo usePersistence:usePersistence credentialsProvider:credentialsProvider userExecutor:std::move(userExecutor) - workerDispatchQueue:workerDispatchQueue]; + workerQueue:std::move(workerQueue)]; } - (instancetype)initWithDatabaseInfo:(const DatabaseInfo &)databaseInfo @@ -120,19 +125,18 @@ - (instancetype)initWithDatabaseInfo:(const DatabaseInfo &)databaseInfo credentialsProvider: (CredentialsProvider *)credentialsProvider // no passing ownership userExecutor:(std::unique_ptr)userExecutor - workerDispatchQueue:(FSTDispatchQueue *)workerDispatchQueue { + workerQueue:(std::unique_ptr)workerQueue { if (self = [super init]) { _databaseInfo = databaseInfo; _credentialsProvider = credentialsProvider; _userExecutor = std::move(userExecutor); - _workerDispatchQueue = workerDispatchQueue; + _workerQueue = std::move(workerQueue); auto userPromise = std::make_shared>(); bool initialized = false; __weak __typeof__(self) weakSelf = self; - auto credentialChangeListener = [initialized, userPromise, weakSelf, - workerDispatchQueue](User user) mutable { + auto credentialChangeListener = [initialized, userPromise, weakSelf](User user) mutable { __typeof__(self) strongSelf = weakSelf; if (!strongSelf) return; @@ -140,9 +144,8 @@ - (instancetype)initWithDatabaseInfo:(const DatabaseInfo &)databaseInfo initialized = true; userPromise->set_value(user); } else { - [workerDispatchQueue dispatchAsync:^{ - [strongSelf credentialDidChangeWithUser:user]; - }]; + strongSelf->_workerQueue->Enqueue( + [strongSelf, user] { [strongSelf credentialDidChangeWithUser:user]; }); } }; @@ -151,17 +154,17 @@ - (instancetype)initWithDatabaseInfo:(const DatabaseInfo &)databaseInfo // Defer initialization until we get the current user from the credentialChangeListener. This is // guaranteed to be synchronously dispatched onto our worker queue, so we will be initialized // before any subsequently queued work runs. - [_workerDispatchQueue dispatchAsync:^{ + _workerQueue->Enqueue([self, userPromise, usePersistence] { User user = userPromise->get_future().get(); [self initializeWithUser:user usePersistence:usePersistence]; - }]; + }); } return self; } - (void)initializeWithUser:(const User &)user usePersistence:(BOOL)usePersistence { // Do all of our initialization on our own dispatch queue. - [self.workerDispatchQueue verifyIsCurrentQueue]; + _workerQueue->VerifyIsCurrentQueue(); LOG_DEBUG("Initializing. Current user: %s", user.uid()); // Note: The initialization work must all be synchronous (we can't dispatch more work) since @@ -194,12 +197,12 @@ - (void)initializeWithUser:(const User &)user usePersistence:(BOOL)usePersistenc _localStore = [[FSTLocalStore alloc] initWithPersistence:_persistence initialUser:user]; FSTDatastore *datastore = [FSTDatastore datastoreWithDatabase:self.databaseInfo - workerDispatchQueue:self.workerDispatchQueue + workerQueue:_workerQueue.get() credentials:_credentialsProvider]; _remoteStore = [[FSTRemoteStore alloc] initWithLocalStore:_localStore datastore:datastore - workerDispatchQueue:self.workerDispatchQueue]; + workerQueue:_workerQueue.get()]; _syncEngine = [[FSTSyncEngine alloc] initWithLocalStore:_localStore remoteStore:_remoteStore @@ -219,7 +222,7 @@ - (void)initializeWithUser:(const User &)user usePersistence:(BOOL)usePersistenc } - (void)credentialDidChangeWithUser:(const User &)user { - [self.workerDispatchQueue verifyIsCurrentQueue]; + _workerQueue->VerifyIsCurrentQueue(); LOG_DEBUG("Credential Changed. Current user: %s", user.uid()); [self.syncEngine credentialDidChangeWithUser:user]; @@ -230,25 +233,25 @@ - (void)applyChangedOnlineState:(OnlineState)onlineState { } - (void)disableNetworkWithCompletion:(nullable FSTVoidErrorBlock)completion { - [self.workerDispatchQueue dispatchAsync:^{ + _workerQueue->Enqueue([self, completion] { [self.remoteStore disableNetwork]; if (completion) { self->_userExecutor->Execute([=] { completion(nil); }); } - }]; + }); } - (void)enableNetworkWithCompletion:(nullable FSTVoidErrorBlock)completion { - [self.workerDispatchQueue dispatchAsync:^{ + _workerQueue->Enqueue([self, completion] { [self.remoteStore enableNetwork]; if (completion) { self->_userExecutor->Execute([=] { completion(nil); }); } - }]; + }); } - (void)shutdownWithCompletion:(nullable FSTVoidErrorBlock)completion { - [self.workerDispatchQueue dispatchAsync:^{ + _workerQueue->Enqueue([self, completion] { self->_credentialsProvider->SetCredentialChangeListener(nullptr); [self.remoteStore shutdown]; @@ -256,7 +259,7 @@ - (void)shutdownWithCompletion:(nullable FSTVoidErrorBlock)completion { if (completion) { self->_userExecutor->Execute([=] { completion(nil); }); } - }]; + }); } - (FSTQueryListener *)listenToQuery:(FSTQuery *)query @@ -266,23 +269,19 @@ - (FSTQueryListener *)listenToQuery:(FSTQuery *)query options:options viewSnapshotHandler:viewSnapshotHandler]; - [self.workerDispatchQueue dispatchAsync:^{ - [self.eventManager addListener:listener]; - }]; + _workerQueue->Enqueue([self, listener] { [self.eventManager addListener:listener]; }); return listener; } - (void)removeListener:(FSTQueryListener *)listener { - [self.workerDispatchQueue dispatchAsync:^{ - [self.eventManager removeListener:listener]; - }]; + _workerQueue->Enqueue([self, listener] { [self.eventManager removeListener:listener]; }); } - (void)getDocumentFromLocalCache:(FIRDocumentReference *)doc completion:(void (^)(FIRDocumentSnapshot *_Nullable document, NSError *_Nullable error))completion { - [self.workerDispatchQueue dispatchAsync:^{ + _workerQueue->Enqueue([self, doc, completion] { FSTMaybeDocument *maybeDoc = [self.localStore readDocument:doc.key]; FIRDocumentSnapshot *_Nullable result = nil; NSError *_Nullable error = nil; @@ -315,13 +314,13 @@ - (void)getDocumentFromLocalCache:(FIRDocumentReference *)doc if (completion) { self->_userExecutor->Execute([=] { completion(result, error); }); } - }]; + }); } - (void)getDocumentsFromLocalCache:(FIRQuery *)query completion:(void (^)(FIRQuerySnapshot *_Nullable query, NSError *_Nullable error))completion { - [self.workerDispatchQueue dispatchAsync:^{ + _workerQueue->Enqueue([self, query, completion] { FSTDocumentDictionary *docs = [self.localStore executeQuery:query.query]; FSTView *view = [[FSTView alloc] initWithQuery:query.query remoteDocuments:DocumentKeySet{}]; @@ -343,12 +342,12 @@ - (void)getDocumentsFromLocalCache:(FIRQuery *)query if (completion) { self->_userExecutor->Execute([=] { completion(result, nil); }); } - }]; + }); } - (void)writeMutations:(NSArray *)mutations completion:(nullable FSTVoidErrorBlock)completion { - [self.workerDispatchQueue dispatchAsync:^{ + _workerQueue->Enqueue([self, mutations, completion] { if (mutations.count == 0) { if (completion) { self->_userExecutor->Execute([=] { completion(nil); }); @@ -362,16 +361,16 @@ - (void)writeMutations:(NSArray *)mutations } }]; } - }]; + }); }; - (void)transactionWithRetries:(int)retries updateBlock:(FSTTransactionBlock)updateBlock completion:(FSTVoidIDErrorBlock)completion { - [self.workerDispatchQueue dispatchAsync:^{ + _workerQueue->Enqueue([self, retries, updateBlock, completion] { [self.syncEngine transactionWithRetries:retries - workerDispatchQueue:self.workerDispatchQueue + workerQueue:_workerQueue.get() updateBlock:updateBlock completion:^(id _Nullable result, NSError *_Nullable error) { // Dispatch the result back onto the user dispatch queue. @@ -379,7 +378,7 @@ - (void)transactionWithRetries:(int)retries self->_userExecutor->Execute([=] { completion(result, error); }); } }]; - }]; + }); } - (const DatabaseInfo *)databaseInfo { diff --git a/Firestore/Source/Core/FSTSyncEngine.h b/Firestore/Source/Core/FSTSyncEngine.h index 3bb35e3665a..b4c4af93c22 100644 --- a/Firestore/Source/Core/FSTSyncEngine.h +++ b/Firestore/Source/Core/FSTSyncEngine.h @@ -21,8 +21,8 @@ #include "Firestore/core/src/firebase/firestore/auth/user.h" #include "Firestore/core/src/firebase/firestore/model/types.h" +#include "Firestore/core/src/firebase/firestore/util/async_queue.h" -@class FSTDispatchQueue; @class FSTLocalStore; @class FSTMutation; @class FSTQuery; @@ -58,7 +58,7 @@ NS_ASSUME_NONNULL_BEGIN * sending to the backend. * * The SyncEngine’s methods should only ever be called by methods running on our own worker - * dispatch queue. + * queue. */ @interface FSTSyncEngine : NSObject @@ -97,12 +97,12 @@ NS_ASSUME_NONNULL_BEGIN * Runs the given transaction block up to retries times and then calls completion. * * @param retries The number of times to try before giving up. - * @param workerDispatchQueue The queue to dispatch sync engine calls to. + * @param workerQueue The queue to dispatch sync engine calls to. * @param updateBlock The block to call to execute the user's transaction. * @param completion The block to call when the transaction is finished or failed. */ - (void)transactionWithRetries:(int)retries - workerDispatchQueue:(FSTDispatchQueue *)workerDispatchQueue + workerQueue:(firebase::firestore::util::AsyncQueue *)workerQueue updateBlock:(FSTTransactionBlock)updateBlock completion:(FSTVoidIDErrorBlock)completion; diff --git a/Firestore/Source/Core/FSTSyncEngine.mm b/Firestore/Source/Core/FSTSyncEngine.mm index e21cd19991e..c8b1d7fd4c2 100644 --- a/Firestore/Source/Core/FSTSyncEngine.mm +++ b/Firestore/Source/Core/FSTSyncEngine.mm @@ -35,7 +35,6 @@ #import "Firestore/Source/Model/FSTDocumentSet.h" #import "Firestore/Source/Model/FSTMutationBatch.h" #import "Firestore/Source/Remote/FSTRemoteEvent.h" -#import "Firestore/Source/Util/FSTDispatchQueue.h" #include "Firestore/core/src/firebase/firestore/auth/user.h" #include "Firestore/core/src/firebase/firestore/core/target_id_generator.h" @@ -54,6 +53,7 @@ using firebase::firestore::model::OnlineState; using firebase::firestore::model::SnapshotVersion; using firebase::firestore::model::TargetId; +using firebase::firestore::util::AsyncQueue; NS_ASSUME_NONNULL_BEGIN @@ -277,42 +277,43 @@ - (void)addMutationCompletionBlock:(FSTVoidErrorBlock)completion batchID:(BatchI * reads are performed before any writes. Transactions must be performed while online. */ - (void)transactionWithRetries:(int)retries - workerDispatchQueue:(FSTDispatchQueue *)workerDispatchQueue + workerQueue:(AsyncQueue *)workerQueue updateBlock:(FSTTransactionBlock)updateBlock completion:(FSTVoidIDErrorBlock)completion { - [workerDispatchQueue verifyIsCurrentQueue]; + workerQueue->VerifyIsCurrentQueue(); HARD_ASSERT(retries >= 0, "Got negative number of retries for transaction"); FSTTransaction *transaction = [self.remoteStore transaction]; updateBlock(transaction, ^(id _Nullable result, NSError *_Nullable error) { - [workerDispatchQueue dispatchAsync:^{ - if (error) { - completion(nil, error); - return; - } - [transaction commitWithCompletion:^(NSError *_Nullable transactionError) { - if (!transactionError) { - completion(result, nil); - return; - } - // TODO(b/35201829): Only retry on real transaction failures. - if (retries == 0) { - NSError *wrappedError = - [NSError errorWithDomain:FIRFirestoreErrorDomain - code:FIRFirestoreErrorCodeFailedPrecondition - userInfo:@{ - NSLocalizedDescriptionKey : @"Transaction failed all retries.", - NSUnderlyingErrorKey : transactionError - }]; - completion(nil, wrappedError); - return; - } - [workerDispatchQueue verifyIsCurrentQueue]; - return [self transactionWithRetries:(retries - 1) - workerDispatchQueue:workerDispatchQueue - updateBlock:updateBlock - completion:completion]; - }]; - }]; + workerQueue->Enqueue( + [self, retries, workerQueue, updateBlock, completion, transaction, result, error] { + if (error) { + completion(nil, error); + return; + } + [transaction commitWithCompletion:^(NSError *_Nullable transactionError) { + if (!transactionError) { + completion(result, nil); + return; + } + // TODO(b/35201829): Only retry on real transaction failures. + if (retries == 0) { + NSError *wrappedError = + [NSError errorWithDomain:FIRFirestoreErrorDomain + code:FIRFirestoreErrorCodeFailedPrecondition + userInfo:@{ + NSLocalizedDescriptionKey : @"Transaction failed all retries.", + NSUnderlyingErrorKey : transactionError + }]; + completion(nil, wrappedError); + return; + } + workerQueue->VerifyIsCurrentQueue(); + return [self transactionWithRetries:(retries - 1) + workerQueue:workerQueue + updateBlock:updateBlock + completion:completion]; + }]; + }); }); } diff --git a/Firestore/Source/Remote/FSTDatastore.h b/Firestore/Source/Remote/FSTDatastore.h index b5f31840940..fbb39a43eb6 100644 --- a/Firestore/Source/Remote/FSTDatastore.h +++ b/Firestore/Source/Remote/FSTDatastore.h @@ -28,10 +28,10 @@ #include "Firestore/core/src/firebase/firestore/model/database_id.h" #include "Firestore/core/src/firebase/firestore/model/document_key.h" #include "Firestore/core/src/firebase/firestore/remote/datastore.h" +#include "Firestore/core/src/firebase/firestore/util/async_queue.h" #include "absl/memory/memory.h" #include "absl/strings/string_view.h" -@class FSTDispatchQueue; @class FSTMutation; @class FSTMutationResult; @class FSTQueryData; @@ -56,14 +56,14 @@ NS_ASSUME_NONNULL_BEGIN /** Creates a new Datastore instance with the given database info. */ + (instancetype)datastoreWithDatabase:(const firebase::firestore::core::DatabaseInfo *)databaseInfo - workerDispatchQueue:(FSTDispatchQueue *)workerDispatchQueue + workerQueue:(firebase::firestore::util::AsyncQueue *)workerQueue credentials:(firebase::firestore::auth::CredentialsProvider *) credentials; // no passing ownership - (instancetype)init __attribute__((unavailable("Use a static constructor method."))); - (instancetype)initWithDatabaseInfo:(const firebase::firestore::core::DatabaseInfo *)databaseInfo - workerDispatchQueue:(FSTDispatchQueue *)workerDispatchQueue + workerQueue:(firebase::firestore::util::AsyncQueue *)workerQueue credentials:(firebase::firestore::auth::CredentialsProvider *) credentials // no passing ownership NS_DESIGNATED_INITIALIZER; diff --git a/Firestore/Source/Remote/FSTDatastore.mm b/Firestore/Source/Remote/FSTDatastore.mm index 2d0a710f947..2bf686ec1bd 100644 --- a/Firestore/Source/Remote/FSTDatastore.mm +++ b/Firestore/Source/Remote/FSTDatastore.mm @@ -28,13 +28,13 @@ #import "Firestore/Source/Model/FSTMutation.h" #import "Firestore/Source/Remote/FSTSerializerBeta.h" #import "Firestore/Source/Remote/FSTStream.h" -#import "Firestore/Source/Util/FSTDispatchQueue.h" #include "Firestore/core/src/firebase/firestore/auth/credentials_provider.h" #include "Firestore/core/src/firebase/firestore/auth/token.h" #include "Firestore/core/src/firebase/firestore/core/database_info.h" #include "Firestore/core/src/firebase/firestore/model/database_id.h" #include "Firestore/core/src/firebase/firestore/model/document_key.h" +#include "Firestore/core/src/firebase/firestore/util/async_queue.h" #include "Firestore/core/src/firebase/firestore/util/error_apple.h" #include "Firestore/core/src/firebase/firestore/util/hard_assert.h" #include "Firestore/core/src/firebase/firestore/util/log.h" @@ -52,6 +52,7 @@ using firebase::firestore::remote::GrpcConnection; using firebase::firestore::remote::WatchStream; using firebase::firestore::remote::WriteStream; +using util::AsyncQueue; NS_ASSUME_NONNULL_BEGIN @@ -64,8 +65,6 @@ @interface FSTDatastore () -@property(nonatomic, strong, readonly) FSTDispatchQueue *workerDispatchQueue; - /** * An object for getting an auth token before each request. Does not own the CredentialsProvider * instance. @@ -77,28 +76,29 @@ @interface FSTDatastore () @end @implementation FSTDatastore { + AsyncQueue *_workerQueue; std::shared_ptr _datastore; } + (instancetype)datastoreWithDatabase:(const DatabaseInfo *)databaseInfo - workerDispatchQueue:(FSTDispatchQueue *)workerDispatchQueue + workerQueue:(AsyncQueue *)workerQueue credentials:(CredentialsProvider *)credentials { return [[FSTDatastore alloc] initWithDatabaseInfo:databaseInfo - workerDispatchQueue:workerDispatchQueue + workerQueue:workerQueue credentials:credentials]; } - (instancetype)initWithDatabaseInfo:(const DatabaseInfo *)databaseInfo - workerDispatchQueue:(FSTDispatchQueue *)workerDispatchQueue + workerQueue:(AsyncQueue *)workerQueue credentials:(CredentialsProvider *)credentials { if (self = [super init]) { _databaseInfo = databaseInfo; - _workerDispatchQueue = workerDispatchQueue; + _workerQueue = workerQueue; _credentials = credentials; _serializer = [[FSTSerializerBeta alloc] initWithDatabaseID:&databaseInfo->database_id()]; - _datastore = std::make_shared(*_databaseInfo, [_workerDispatchQueue implementation], - _credentials, _serializer); + _datastore = + std::make_shared(*_databaseInfo, _workerQueue, _credentials, _serializer); _datastore->Start(); if (!databaseInfo->ssl_enabled()) { GrpcConnection::UseInsecureChannel(databaseInfo->host()); diff --git a/Firestore/Source/Remote/FSTOnlineStateTracker.h b/Firestore/Source/Remote/FSTOnlineStateTracker.h index 7e5449bd975..56aad0539a8 100644 --- a/Firestore/Source/Remote/FSTOnlineStateTracker.h +++ b/Firestore/Source/Remote/FSTOnlineStateTracker.h @@ -17,8 +17,8 @@ #import #include "Firestore/core/src/firebase/firestore/model/types.h" +#include "Firestore/core/src/firebase/firestore/util/async_queue.h" -@class FSTDispatchQueue; @protocol FSTOnlineStateDelegate; NS_ASSUME_NONNULL_BEGIN @@ -35,7 +35,7 @@ NS_ASSUME_NONNULL_BEGIN */ @interface FSTOnlineStateTracker : NSObject -- (instancetype)initWithWorkerDispatchQueue:(FSTDispatchQueue *)queue; +- (instancetype)initWithWorkerQueue:(firebase::firestore::util::AsyncQueue *)queue; - (instancetype)init NS_UNAVAILABLE; diff --git a/Firestore/Source/Remote/FSTOnlineStateTracker.mm b/Firestore/Source/Remote/FSTOnlineStateTracker.mm index 101929e203c..be4feab4bfa 100644 --- a/Firestore/Source/Remote/FSTOnlineStateTracker.mm +++ b/Firestore/Source/Remote/FSTOnlineStateTracker.mm @@ -15,27 +15,38 @@ */ #import "Firestore/Source/Remote/FSTOnlineStateTracker.h" + +#include // NOLINT(build/c++11) + #import "Firestore/Source/Remote/FSTRemoteStore.h" -#import "Firestore/Source/Util/FSTDispatchQueue.h" +#include "Firestore/core/src/firebase/firestore/util/executor.h" #include "Firestore/core/src/firebase/firestore/util/hard_assert.h" #include "Firestore/core/src/firebase/firestore/util/log.h" +namespace chr = std::chrono; using firebase::firestore::model::OnlineState; +using firebase::firestore::util::AsyncQueue; +using firebase::firestore::util::DelayedOperation; +using firebase::firestore::util::TimerId; NS_ASSUME_NONNULL_BEGIN +namespace { + // To deal with transient failures, we allow multiple stream attempts before giving up and // transitioning from OnlineState Unknown to Offline. // TODO(mikelehen): This used to be set to 2 as a mitigation for b/66228394. @jdimond thinks that // bug is sufficiently fixed so that we can set this back to 1. If that works okay, we could // potentially remove this logic entirely. -static const int kMaxWatchStreamFailures = 1; +const int kMaxWatchStreamFailures = 1; // To deal with stream attempts that don't succeed or fail in a timely manner, we have a // timeout for OnlineState to reach Online or Offline. If the timeout is reached, we transition // to Offline rather than waiting indefinitely. -static const NSTimeInterval kOnlineStateTimeout = 10; +const AsyncQueue::Milliseconds kOnlineStateTimeout = chr::seconds(10); + +} // namespace @interface FSTOnlineStateTracker () @@ -48,28 +59,29 @@ @interface FSTOnlineStateTracker () */ @property(nonatomic, assign) int watchStreamFailures; -/** - * A timer that elapses after kOnlineStateTimeout, at which point we transition from OnlineState - * Unknown to Offline without waiting for the stream to actually fail (kMaxWatchStreamFailures - * times). - */ -@property(nonatomic, strong, nullable) FSTDelayedCallback *onlineStateTimer; - /** * Whether the client should log a warning message if it fails to connect to the backend * (initially YES, cleared after a successful stream, or if we've logged the message already). */ @property(nonatomic, assign) BOOL shouldWarnClientIsOffline; -/** The FSTDispatchQueue to use for running timers (and to call onlineStateDelegate). */ -@property(nonatomic, strong, readonly) FSTDispatchQueue *queue; - @end -@implementation FSTOnlineStateTracker -- (instancetype)initWithWorkerDispatchQueue:(FSTDispatchQueue *)queue { +@implementation FSTOnlineStateTracker { + /** + * A timer that elapses after kOnlineStateTimeout, at which point we transition from OnlineState + * Unknown to Offline without waiting for the stream to actually fail (kMaxWatchStreamFailures + * times). + */ + DelayedOperation _onlineStateTimer; + + /** The worker queue to use for running timers (and to call onlineStateDelegate). */ + AsyncQueue *_workerQueue; +} + +- (instancetype)initWithWorkerQueue:(AsyncQueue *)workerQueue { if (self = [super init]) { - _queue = queue; + _workerQueue = workerQueue; _state = OnlineState::Unknown; _shouldWarnClientIsOffline = YES; } @@ -80,25 +92,22 @@ - (void)handleWatchStreamStart { if (self.watchStreamFailures == 0) { [self setAndBroadcastState:OnlineState::Unknown]; - HARD_ASSERT(!self.onlineStateTimer, "onlineStateTimer shouldn't be started yet"); - self.onlineStateTimer = [self.queue - dispatchAfterDelay:kOnlineStateTimeout - timerID:FSTTimerIDOnlineStateTimeout - block:^{ - self.onlineStateTimer = nil; - HARD_ASSERT( - self.state == OnlineState::Unknown, - "Timer should be canceled if we transitioned to a different state."); - [self logClientOfflineWarningIfNecessaryWithReason: - [NSString - stringWithFormat:@"Backend didn't respond within %f seconds.", - kOnlineStateTimeout]]; - [self setAndBroadcastState:OnlineState::Offline]; - - // NOTE: handleWatchStreamFailure will continue to increment - // watchStreamFailures even though we are already marked Offline but this is - // non-harmful. - }]; + HARD_ASSERT(!_onlineStateTimer, "_onlineStateTimer shouldn't be started yet"); + _onlineStateTimer = + _workerQueue->EnqueueAfterDelay(kOnlineStateTimeout, TimerId::OnlineStateTimeout, [self] { + _onlineStateTimer = {}; + HARD_ASSERT(self.state == OnlineState::Unknown, + "Timer should be canceled if we transitioned to a different state."); + [self logClientOfflineWarningIfNecessaryWithReason: + [NSString stringWithFormat:@"Backend didn't respond within %lld seconds.", + chr::duration_cast(kOnlineStateTimeout) + .count()]]; + [self setAndBroadcastState:OnlineState::Offline]; + + // NOTE: handleWatchStreamFailure will continue to increment + // watchStreamFailures even though we are already marked Offline but this is + // non-harmful. + }); } } @@ -109,7 +118,7 @@ - (void)handleWatchStreamFailure:(NSError *)error { // To get to OnlineState::Online, updateState: must have been called which would have reset // our heuristics. HARD_ASSERT(self.watchStreamFailures == 0, "watchStreamFailures must be 0"); - HARD_ASSERT(!self.onlineStateTimer, "onlineStateTimer must be nil"); + HARD_ASSERT(!_onlineStateTimer, "_onlineStateTimer must not be set yet"); } else { self.watchStreamFailures++; if (self.watchStreamFailures >= kMaxWatchStreamFailures) { @@ -158,10 +167,7 @@ - (void)logClientOfflineWarningIfNecessaryWithReason:(NSString *)reason { } - (void)clearOnlineStateTimer { - if (self.onlineStateTimer) { - [self.onlineStateTimer cancel]; - self.onlineStateTimer = nil; - } + _onlineStateTimer.Cancel(); } @end diff --git a/Firestore/Source/Remote/FSTRemoteStore.h b/Firestore/Source/Remote/FSTRemoteStore.h index c513b32c891..9909b5e20e6 100644 --- a/Firestore/Source/Remote/FSTRemoteStore.h +++ b/Firestore/Source/Remote/FSTRemoteStore.h @@ -20,6 +20,7 @@ #include "Firestore/core/src/firebase/firestore/auth/user.h" #include "Firestore/core/src/firebase/firestore/model/types.h" +#include "Firestore/core/src/firebase/firestore/util/async_queue.h" @class FSTDatastore; @class FSTLocalStore; @@ -28,7 +29,6 @@ @class FSTQueryData; @class FSTRemoteEvent; @class FSTTransaction; -@class FSTDispatchQueue; NS_ASSUME_NONNULL_BEGIN @@ -104,7 +104,7 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithLocalStore:(FSTLocalStore *)localStore datastore:(FSTDatastore *)datastore - workerDispatchQueue:(FSTDispatchQueue *)queue; + workerQueue:(firebase::firestore::util::AsyncQueue *)queue; - (instancetype)init NS_UNAVAILABLE; diff --git a/Firestore/Source/Remote/FSTRemoteStore.mm b/Firestore/Source/Remote/FSTRemoteStore.mm index c9041dc278f..07818a25a4d 100644 --- a/Firestore/Source/Remote/FSTRemoteStore.mm +++ b/Firestore/Source/Remote/FSTRemoteStore.mm @@ -53,6 +53,7 @@ using firebase::firestore::model::TargetId; using firebase::firestore::remote::WatchStream; using firebase::firestore::remote::WriteStream; +using util::AsyncQueue; NS_ASSUME_NONNULL_BEGIN @@ -121,14 +122,14 @@ @implementation FSTRemoteStore { - (instancetype)initWithLocalStore:(FSTLocalStore *)localStore datastore:(FSTDatastore *)datastore - workerDispatchQueue:(FSTDispatchQueue *)queue { + workerQueue:(AsyncQueue *)queue { if (self = [super init]) { _localStore = localStore; _datastore = datastore; _listenTargets = [NSMutableDictionary dictionary]; _writePipeline = [NSMutableArray array]; - _onlineStateTracker = [[FSTOnlineStateTracker alloc] initWithWorkerDispatchQueue:queue]; + _onlineStateTracker = [[FSTOnlineStateTracker alloc] initWithWorkerQueue:queue]; // Create streams (but note they're not started yet) _watchStream = [self.datastore createWatchStreamWithDelegate:self]; diff --git a/Firestore/Source/Util/FSTAsyncQueryListener.h b/Firestore/Source/Util/FSTAsyncQueryListener.h index 06471d830f7..30a1a733699 100644 --- a/Firestore/Source/Util/FSTAsyncQueryListener.h +++ b/Firestore/Source/Util/FSTAsyncQueryListener.h @@ -22,7 +22,6 @@ NS_ASSUME_NONNULL_BEGIN -@class FSTDispatchQueue; @class FSTQueryListener; /** @@ -30,7 +29,7 @@ NS_ASSUME_NONNULL_BEGIN */ @interface FSTAsyncQueryListener : NSObject -- (instancetype)initWithExecutor:(firebase::firestore::util::internal::Executor*)executor +- (instancetype)initWithExecutor:(firebase::firestore::util::Executor*)executor snapshotHandler:(FSTViewSnapshotHandler)snapshotHandler NS_DESIGNATED_INITIALIZER; - (instancetype)init NS_UNAVAILABLE; diff --git a/Firestore/Source/Util/FSTAsyncQueryListener.mm b/Firestore/Source/Util/FSTAsyncQueryListener.mm index 81dd41f8592..2a02b3dc4a8 100644 --- a/Firestore/Source/Util/FSTAsyncQueryListener.mm +++ b/Firestore/Source/Util/FSTAsyncQueryListener.mm @@ -16,9 +16,7 @@ #import "Firestore/Source/Util/FSTAsyncQueryListener.h" -#import "Firestore/Source/Util/FSTDispatchQueue.h" - -using firebase::firestore::util::internal::Executor; +using firebase::firestore::util::Executor; @implementation FSTAsyncQueryListener { volatile BOOL _muted; diff --git a/Firestore/Source/Util/FSTDispatchQueue.h b/Firestore/Source/Util/FSTDispatchQueue.h deleted file mode 100644 index 7e7b04abecb..00000000000 --- a/Firestore/Source/Util/FSTDispatchQueue.h +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright 2017 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import - -#include "Firestore/core/src/firebase/firestore/util/async_queue.h" - -NS_ASSUME_NONNULL_BEGIN - -/** - * Well-known "timer" IDs used when scheduling delayed callbacks on the FSTDispatchQueue. These IDs - * can then be used from tests to check for the presence of callbacks or to run them early. - */ -typedef NS_ENUM(NSInteger, FSTTimerID) { - /** All can be used with runDelayedCallbacksUntil: to run all timers. */ - FSTTimerIDAll, - - /** - * The following 4 timers are used in FSTStream for the listen and write streams. The "Idle" timer - * is used to close the stream due to inactivity. The "ConnectionBackoff" timer is used to - * restart a stream once the appropriate backoff delay has elapsed. - */ - FSTTimerIDListenStreamIdle, - FSTTimerIDListenStreamConnectionBackoff, - FSTTimerIDWriteStreamIdle, - FSTTimerIDWriteStreamConnectionBackoff, - - /** - * A timer used in FSTOnlineStateTracker to transition from OnlineState Unknown to Offline - * after a set timeout, rather than waiting indefinitely for success or failure. - */ - FSTTimerIDOnlineStateTimeout -}; - -/** - * Handle to a callback scheduled via [FSTDispatchQueue dispatchAfterDelay:]. Supports cancellation - * via the cancel method. - */ -@interface FSTDelayedCallback : NSObject - -/** - * Cancels the callback if it hasn't already been executed or canceled. - * - * As long as the callback has not yet been run, calling cancel() (from a callback already running - * on the dispatch queue) provides a guarantee that the operation will not be run. - */ -- (void)cancel; - -@end - -@interface FSTDispatchQueue : NSObject - -/** Creates and returns an FSTDispatchQueue wrapping the specified dispatch_queue_t. */ -+ (instancetype)queueWith:(dispatch_queue_t)dispatchQueue; - -- (instancetype)initWithQueue:(dispatch_queue_t)queue NS_DESIGNATED_INITIALIZER; - -- (instancetype)init __attribute__((unavailable("Use static constructor method."))); - -/** - * Asserts that we are already running on this queue (actually, we can only verify that the - * queue's label is the same, but hopefully that's good enough.) - */ -- (void)verifyIsCurrentQueue; - -/** - * Declares that we are already executing on the correct dispatch_queue_t and would like to - * officially execute code on behalf of this FSTDispatchQueue. To be used only when called back - * by some other API directly onto our queue. This allows us to safely dispatch directly onto the - * worker queue without destroying the invariants this class helps us maintain. - */ -- (void)enterCheckedOperation:(void (^)(void))block; - -/** - * Same as dispatch_async() except it asserts that we're not already on the queue, since this - * generally indicates a bug (and can lead to re-ordering of operations, etc). - * - * @param block The block to run. - */ -- (void)dispatchAsync:(void (^)(void))block; - -/** - * Unlike dispatchAsync: this method does not require you to dispatch to a different queue than - * the current one (thus it is equivalent to a raw dispatch_async()). - * - * This is useful, e.g. for dispatching to the user's queue directly from user API call (in which - * case we don't know if we're already on the user's queue or not). - * - * @param block The block to run. - */ -- (void)dispatchAsyncAllowingSameQueue:(void (^)(void))block; - -/** - * Wrapper for dispatch_sync(). Mostly meant for use in tests. - * - * @param block The block to run. - */ -- (void)dispatchSync:(void (^)(void))block; - -/** - * Schedules a callback after the specified delay. - * - * Unlike dispatchAsync: this method does not require you to dispatch to a different queue than - * the current one. - * - * The returned FSTDelayedCallback handle can be used to cancel the callback prior to its running. - * - * @param block The block to run. - * @param delay The delay (in seconds) after which to run the block. - * @param timerID An FSTTimerID that can be used from tests to check for the presence of this - * callback or to schedule it to run early. - * @return A FSTDelayedCallback instance that can be used for cancellation. - */ -- (FSTDelayedCallback *)dispatchAfterDelay:(NSTimeInterval)delay - timerID:(FSTTimerID)timerID - block:(void (^)(void))block; - -/** - * For Tests: Determine if a delayed callback with a particular FSTTimerID exists. - */ -- (BOOL)containsDelayedCallbackWithTimerID:(FSTTimerID)timerID; - -/** - * For Tests: Runs delayed callbacks early, blocking until completion. - * - * @param lastTimerID Only delayed callbacks up to and including one that was scheduled using this - * FSTTimerID will be run. Method throws if no matching callback exists. - */ -- (void)runDelayedCallbacksUntil:(FSTTimerID)lastTimerID; - -/** The underlying wrapped dispatch_queue_t */ -@property(nonatomic, strong, readonly) dispatch_queue_t queue; - -- (firebase::firestore::util::AsyncQueue *)implementation; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Firestore/Source/Util/FSTDispatchQueue.mm b/Firestore/Source/Util/FSTDispatchQueue.mm deleted file mode 100644 index 76ea32194b6..00000000000 --- a/Firestore/Source/Util/FSTDispatchQueue.mm +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright 2017 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import - -#include -#include - -#import "Firestore/Source/Util/FSTDispatchQueue.h" - -#include "Firestore/core/src/firebase/firestore/util/executor_libdispatch.h" -#include "Firestore/core/src/firebase/firestore/util/hard_assert.h" -#include "absl/memory/memory.h" - -using firebase::firestore::util::AsyncQueue; -using firebase::firestore::util::DelayedOperation; -using firebase::firestore::util::TimerId; -using firebase::firestore::util::internal::Executor; -using firebase::firestore::util::internal::ExecutorLibdispatch; - -NS_ASSUME_NONNULL_BEGIN - -#pragma mark - FSTDelayedCallback - -@interface FSTDelayedCallback () { - DelayedOperation _impl; -} - -@end - -@implementation FSTDelayedCallback - -- (instancetype)initWithImpl:(DelayedOperation &&)impl { - if (self = [super init]) { - _impl = std::move(impl); - } - return self; -} - -- (void)cancel { - _impl.Cancel(); -} - -@end - -#pragma mark - FSTDispatchQueue - -@implementation FSTDispatchQueue { - std::unique_ptr _impl; -} - -- (AsyncQueue *)implementation { - return _impl.get(); -} - -+ (TimerId)convertTimerId:(FSTTimerID)objcTimerID { - const TimerId converted = static_cast(objcTimerID); - switch (converted) { - case TimerId::All: - case TimerId::ListenStreamIdle: - case TimerId::ListenStreamConnectionBackoff: - case TimerId::WriteStreamIdle: - case TimerId::WriteStreamConnectionBackoff: - case TimerId::OnlineStateTimeout: - return converted; - default: - HARD_FAIL("Unknown value of enum FSTTimerID."); - } -} - -+ (instancetype)queueWith:(dispatch_queue_t)dispatchQueue { - return [[FSTDispatchQueue alloc] initWithQueue:dispatchQueue]; -} - -- (instancetype)initWithQueue:(dispatch_queue_t)queue { - if (self = [super init]) { - _queue = queue; - auto executor = absl::make_unique(queue); - _impl = absl::make_unique(std::move(executor)); - } - return self; -} - -- (void)verifyIsCurrentQueue { - _impl->VerifyIsCurrentQueue(); -} - -- (void)enterCheckedOperation:(void (^)(void))block { - _impl->ExecuteBlocking([block] { block(); }); -} - -- (void)dispatchAsync:(void (^)(void))block { - _impl->Enqueue([block] { block(); }); -} - -- (void)dispatchAsyncAllowingSameQueue:(void (^)(void))block { - _impl->EnqueueRelaxed([block] { block(); }); -} - -- (void)dispatchSync:(void (^)(void))block { - _impl->EnqueueBlocking([block] { block(); }); -} - -- (FSTDelayedCallback *)dispatchAfterDelay:(NSTimeInterval)delay - timerID:(FSTTimerID)timerID - block:(void (^)(void))block { - const AsyncQueue::Milliseconds delayMs = - std::chrono::milliseconds(static_cast(delay * 1000)); - const TimerId convertedTimerId = [FSTDispatchQueue convertTimerId:timerID]; - DelayedOperation delayed_operation = - _impl->EnqueueAfterDelay(delayMs, convertedTimerId, [block] { block(); }); - return [[FSTDelayedCallback alloc] initWithImpl:std::move(delayed_operation)]; -} - -- (BOOL)containsDelayedCallbackWithTimerID:(FSTTimerID)timerID { - return _impl->IsScheduled([FSTDispatchQueue convertTimerId:timerID]); -} - -- (void)runDelayedCallbacksUntil:(FSTTimerID)lastTimerID { - _impl->RunScheduledOperationsUntil([FSTDispatchQueue convertTimerId:lastTimerID]); -} - -@end - -NS_ASSUME_NONNULL_END diff --git a/Firestore/core/src/firebase/firestore/remote/connectivity_monitor_apple.mm b/Firestore/core/src/firebase/firestore/remote/connectivity_monitor_apple.mm index dc26dc2f928..558b963536c 100644 --- a/Firestore/core/src/firebase/firestore/remote/connectivity_monitor_apple.mm +++ b/Firestore/core/src/firebase/firestore/remote/connectivity_monitor_apple.mm @@ -37,7 +37,7 @@ using NetworkStatus = ConnectivityMonitor::NetworkStatus; using util::AsyncQueue; -using util::internal::ExecutorLibdispatch; +using util::ExecutorLibdispatch; NetworkStatus ToNetworkStatus(SCNetworkReachabilityFlags flags) { if (!(flags & kSCNetworkReachabilityFlagsReachable)) { diff --git a/Firestore/core/src/firebase/firestore/remote/datastore.h b/Firestore/core/src/firebase/firestore/remote/datastore.h index 9c27b420897..626b3459b9c 100644 --- a/Firestore/core/src/firebase/firestore/remote/datastore.h +++ b/Firestore/core/src/firebase/firestore/remote/datastore.h @@ -152,7 +152,7 @@ class Datastore : public std::enable_shared_from_this { // A separate executor dedicated to polling gRPC completion queue (which is // shared for all spawned gRPC streams and calls). - std::unique_ptr rpc_executor_; + std::unique_ptr rpc_executor_; grpc::CompletionQueue grpc_queue_; // TODO(varconst): move `ConnectivityMonitor` to `FSTFirestoreClient`. std::unique_ptr connectivity_monitor_; diff --git a/Firestore/core/src/firebase/firestore/remote/datastore.mm b/Firestore/core/src/firebase/firestore/remote/datastore.mm index b0fa021b74b..59cca4456ac 100644 --- a/Firestore/core/src/firebase/firestore/remote/datastore.mm +++ b/Firestore/core/src/firebase/firestore/remote/datastore.mm @@ -47,8 +47,8 @@ using util::AsyncQueue; using util::Status; using util::StatusOr; -using util::internal::Executor; -using util::internal::ExecutorLibdispatch; +using util::Executor; +using util::ExecutorLibdispatch; namespace { diff --git a/Firestore/core/src/firebase/firestore/util/async_queue.cc b/Firestore/core/src/firebase/firestore/util/async_queue.cc index b42dec330bc..3b8c3c803da 100644 --- a/Firestore/core/src/firebase/firestore/util/async_queue.cc +++ b/Firestore/core/src/firebase/firestore/util/async_queue.cc @@ -25,8 +25,6 @@ namespace firebase { namespace firestore { namespace util { -using internal::Executor; - AsyncQueue::AsyncQueue(std::unique_ptr executor) : executor_{std::move(executor)} { is_operation_in_progress_ = false; diff --git a/Firestore/core/src/firebase/firestore/util/async_queue.h b/Firestore/core/src/firebase/firestore/util/async_queue.h index 8f3e1ad8303..0194e76a575 100644 --- a/Firestore/core/src/firebase/firestore/util/async_queue.h +++ b/Firestore/core/src/firebase/firestore/util/async_queue.h @@ -34,7 +34,7 @@ namespace util { * presence of delayed operations or to run them early. */ enum class TimerId { - /** All can be used with `RunDelayedOperationsUntil` to run all timers. */ + /** All can be used with `RunScheduledOperationsUntil` to run all timers. */ All, /** @@ -73,10 +73,10 @@ enum class TimerId { // and must *not* be used in regular code. class AsyncQueue { public: - using Operation = internal::Executor::Operation; - using Milliseconds = internal::Executor::Milliseconds; + using Operation = Executor::Operation; + using Milliseconds = Executor::Milliseconds; - explicit AsyncQueue(std::unique_ptr executor); + explicit AsyncQueue(std::unique_ptr executor); // Asserts for the caller that it is being invoked as part of an operation on // the `AsyncQueue`. @@ -128,7 +128,7 @@ class AsyncQueue { void ExecuteBlocking(const Operation& operation); // Returns the underlying platform-dependent executor. - internal::Executor* executor() { + Executor* executor() { return executor_.get(); } @@ -159,7 +159,7 @@ class AsyncQueue { void VerifySequentialOrder() const; std::atomic is_operation_in_progress_; - std::unique_ptr executor_; + std::unique_ptr executor_; }; } // namespace util diff --git a/Firestore/core/src/firebase/firestore/util/executor.h b/Firestore/core/src/firebase/firestore/util/executor.h index 27b35f3c04e..6299ae73613 100644 --- a/Firestore/core/src/firebase/firestore/util/executor.h +++ b/Firestore/core/src/firebase/firestore/util/executor.h @@ -61,8 +61,6 @@ class DelayedOperation { std::function cancel_func_; }; -namespace internal { - // An interface to a platform-specific executor of asynchronous operations // (called tasks on other platforms). // @@ -132,7 +130,6 @@ class Executor { virtual absl::optional PopFromSchedule() = 0; }; -} // namespace internal } // namespace util } // namespace firestore } // namespace firebase diff --git a/Firestore/core/src/firebase/firestore/util/executor_libdispatch.h b/Firestore/core/src/firebase/firestore/util/executor_libdispatch.h index 6e9d44f0567..459fa4e6db9 100644 --- a/Firestore/core/src/firebase/firestore/util/executor_libdispatch.h +++ b/Firestore/core/src/firebase/firestore/util/executor_libdispatch.h @@ -49,6 +49,8 @@ void DispatchAsync(dispatch_queue_t queue, std::function&& work); // Similar to `DispatchAsync` but wraps `dispatch_sync_f`. void DispatchSync(dispatch_queue_t queue, std::function work); +} // namespace internal + class TimeSlot; // A serial queue built on top of libdispatch. The operations are run on @@ -83,7 +85,6 @@ class ExecutorLibdispatch : public Executor { std::vector schedule_; }; -} // namespace internal } // namespace util } // namespace firestore } // namespace firebase diff --git a/Firestore/core/src/firebase/firestore/util/executor_libdispatch.mm b/Firestore/core/src/firebase/firestore/util/executor_libdispatch.mm index 9ca5dd9c74c..0b16827cf1e 100644 --- a/Firestore/core/src/firebase/firestore/util/executor_libdispatch.mm +++ b/Firestore/core/src/firebase/firestore/util/executor_libdispatch.mm @@ -23,7 +23,6 @@ namespace firebase { namespace firestore { namespace util { -namespace internal { namespace { @@ -46,6 +45,8 @@ } // namespace +namespace internal { + void DispatchAsync(const dispatch_queue_t queue, std::function&& work) { // Dynamically allocate the function to make sure the object is valid by the // time libdispatch gets to it. @@ -71,8 +72,13 @@ void DispatchSync(const dispatch_queue_t queue, std::function work) { }); } +} // namespace internal + namespace { +using internal::DispatchAsync; +using internal::DispatchSync; + template void RunSynchronized(const ExecutorLibdispatch* const executor, Work&& work) { if (executor->IsCurrentExecutor()) { @@ -297,7 +303,6 @@ void MarkDone() { return result; } -} // namespace internal } // namespace util } // namespace firestore } // namespace firebase diff --git a/Firestore/core/src/firebase/firestore/util/executor_std.cc b/Firestore/core/src/firebase/firestore/util/executor_std.cc index a87ec204087..bfc47fed18e 100644 --- a/Firestore/core/src/firebase/firestore/util/executor_std.cc +++ b/Firestore/core/src/firebase/firestore/util/executor_std.cc @@ -22,7 +22,6 @@ namespace firebase { namespace firestore { namespace util { -namespace internal { namespace { @@ -148,7 +147,6 @@ absl::optional ExecutorStd::PopFromSchedule() { return {std::move(removed.value().tagged)}; } -} // namespace internal } // namespace util } // namespace firestore } // namespace firebase diff --git a/Firestore/core/src/firebase/firestore/util/executor_std.h b/Firestore/core/src/firebase/firestore/util/executor_std.h index 1f1d0837bac..25500367aaf 100644 --- a/Firestore/core/src/firebase/firestore/util/executor_std.h +++ b/Firestore/core/src/firebase/firestore/util/executor_std.h @@ -200,8 +200,6 @@ class Schedule { } // namespace async -namespace internal { - // A serial queue that executes provided operations on a dedicated background // thread, using C++11 standard library functionality. class ExecutorStd : public Executor { @@ -274,7 +272,6 @@ class ExecutorStd : public Executor { std::atomic current_id_{0}; }; -} // namespace internal } // namespace util } // namespace firestore } // namespace firebase diff --git a/Firestore/core/test/firebase/firestore/remote/datastore_test.mm b/Firestore/core/test/firebase/firestore/remote/datastore_test.mm index 686c69e9c34..19692c05792 100644 --- a/Firestore/core/test/firebase/firestore/remote/datastore_test.mm +++ b/Firestore/core/test/firebase/firestore/remote/datastore_test.mm @@ -43,10 +43,10 @@ using util::FakeCredentialsProvider; using util::FakeGrpcQueue; using util::WrapNSString; -using util::internal::ExecutorLibdispatch; +using util::ExecutorLibdispatch; using util::CompletionResult::Error; using util::CompletionResult::Ok; -using util::internal::ExecutorStd; +using util::ExecutorStd; using Type = GrpcCompletion::Type; namespace { diff --git a/Firestore/core/test/firebase/firestore/remote/exponential_backoff_test.cc b/Firestore/core/test/firebase/firestore/remote/exponential_backoff_test.cc index dbc34ef963f..bb43b380c5c 100644 --- a/Firestore/core/test/firebase/firestore/remote/exponential_backoff_test.cc +++ b/Firestore/core/test/firebase/firestore/remote/exponential_backoff_test.cc @@ -24,9 +24,9 @@ #include "gtest/gtest.h" using firebase::firestore::util::AsyncQueue; +using firebase::firestore::util::ExecutorStd; using firebase::firestore::util::TestWithTimeoutMixin; using firebase::firestore::util::TimerId; -using firebase::firestore::util::internal::ExecutorStd; namespace chr = std::chrono; diff --git a/Firestore/core/test/firebase/firestore/remote/grpc_connection_test.cc b/Firestore/core/test/firebase/firestore/remote/grpc_connection_test.cc index beb6d8ad96a..d76ce52bda0 100644 --- a/Firestore/core/test/firebase/firestore/remote/grpc_connection_test.cc +++ b/Firestore/core/test/firebase/firestore/remote/grpc_connection_test.cc @@ -37,10 +37,10 @@ using auth::User; using core::DatabaseInfo; using model::DatabaseId; using util::AsyncQueue; +using util::ExecutorStd; using util::GrpcStreamTester; using util::Status; using util::StatusOr; -using util::internal::ExecutorStd; using NetworkStatus = ConnectivityMonitor::NetworkStatus; namespace { diff --git a/Firestore/core/test/firebase/firestore/remote/grpc_stream_test.cc b/Firestore/core/test/firebase/firestore/remote/grpc_stream_test.cc index 3e7214f5ef6..f8491a48bce 100644 --- a/Firestore/core/test/firebase/firestore/remote/grpc_stream_test.cc +++ b/Firestore/core/test/firebase/firestore/remote/grpc_stream_test.cc @@ -43,6 +43,7 @@ using util::AsyncQueue; using util::ByteBufferToString; using util::CompletionEndState; using util::CreateNoOpConnectivityMonitor; +using util::ExecutorStd; using util::GetFirestoreErrorCodeName; using util::GetGrpcErrorCodeName; using util::GrpcStreamTester; @@ -51,7 +52,6 @@ using util::Status; using util::StringFormat; using util::CompletionResult::Error; using util::CompletionResult::Ok; -using util::internal::ExecutorStd; using Type = GrpcCompletion::Type; namespace { diff --git a/Firestore/core/test/firebase/firestore/remote/grpc_streaming_reader_test.cc b/Firestore/core/test/firebase/firestore/remote/grpc_streaming_reader_test.cc index da3d31ca8b0..4d6df860f46 100644 --- a/Firestore/core/test/firebase/firestore/remote/grpc_streaming_reader_test.cc +++ b/Firestore/core/test/firebase/firestore/remote/grpc_streaming_reader_test.cc @@ -35,6 +35,7 @@ using util::AsyncQueue; using util::ByteBufferToString; using util::CompletionEndState; using util::CreateNoOpConnectivityMonitor; +using util::ExecutorStd; using util::GetFirestoreErrorCodeName; using util::GetGrpcErrorCodeName; using util::GrpcStreamTester; @@ -44,7 +45,6 @@ using util::StatusOr; using util::StringFormat; using util::CompletionResult::Error; using util::CompletionResult::Ok; -using util::internal::ExecutorStd; using Type = GrpcCompletion::Type; class GrpcStreamingReaderTest : public testing::Test { diff --git a/Firestore/core/test/firebase/firestore/remote/grpc_unary_call_test.cc b/Firestore/core/test/firebase/firestore/remote/grpc_unary_call_test.cc index ec0df8996a7..c94b0d28aff 100644 --- a/Firestore/core/test/firebase/firestore/remote/grpc_unary_call_test.cc +++ b/Firestore/core/test/firebase/firestore/remote/grpc_unary_call_test.cc @@ -37,13 +37,13 @@ using util::AsyncQueue; using util::ByteBufferToString; using util::CompletionEndState; using util::CreateNoOpConnectivityMonitor; +using util::ExecutorStd; using util::GrpcStreamTester; using util::MakeByteBuffer; using util::Status; using util::StatusOr; using util::CompletionResult::Error; using util::CompletionResult::Ok; -using util::internal::ExecutorStd; using Type = GrpcCompletion::Type; class GrpcUnaryCallTest : public testing::Test { diff --git a/Firestore/core/test/firebase/firestore/remote/stream_test.mm b/Firestore/core/test/firebase/firestore/remote/stream_test.mm index d138c9c3b8a..4f9dc52ad4b 100644 --- a/Firestore/core/test/firebase/firestore/remote/stream_test.mm +++ b/Firestore/core/test/firebase/firestore/remote/stream_test.mm @@ -56,7 +56,7 @@ using util::MakeByteBuffer; using util::StringFormat; using util::TimerId; -using util::internal::ExecutorStd; +using util::ExecutorStd; using Type = GrpcCompletion::Type; namespace { diff --git a/Firestore/core/test/firebase/firestore/util/async_queue_libdispatch_test.mm b/Firestore/core/test/firebase/firestore/util/async_queue_libdispatch_test.mm index f1ff39433c6..590d6976eea 100644 --- a/Firestore/core/test/firebase/firestore/util/async_queue_libdispatch_test.mm +++ b/Firestore/core/test/firebase/firestore/util/async_queue_libdispatch_test.mm @@ -32,12 +32,12 @@ dispatch_queue_t CreateDispatchQueue() { return dispatch_queue_create("AsyncQueueTests", DISPATCH_QUEUE_SERIAL); } -std::unique_ptr CreateExecutorFromQueue( +std::unique_ptr CreateExecutorFromQueue( const dispatch_queue_t queue) { - return absl::make_unique(queue); + return absl::make_unique(queue); } -std::unique_ptr CreateExecutorLibdispatch() { +std::unique_ptr CreateExecutorLibdispatch() { return CreateExecutorFromQueue(CreateDispatchQueue()); } diff --git a/Firestore/core/test/firebase/firestore/util/async_queue_std_test.cc b/Firestore/core/test/firebase/firestore/util/async_queue_std_test.cc index 9e69ad02f97..24f43e8c41d 100644 --- a/Firestore/core/test/firebase/firestore/util/async_queue_std_test.cc +++ b/Firestore/core/test/firebase/firestore/util/async_queue_std_test.cc @@ -27,8 +27,8 @@ namespace util { namespace { -std::unique_ptr ExecutorFactory() { - return absl::make_unique(); +std::unique_ptr ExecutorFactory() { + return absl::make_unique(); } } // namespace diff --git a/Firestore/core/test/firebase/firestore/util/async_queue_test.h b/Firestore/core/test/firebase/firestore/util/async_queue_test.h index 61c7ab61385..b0e5c7e3016 100644 --- a/Firestore/core/test/firebase/firestore/util/async_queue_test.h +++ b/Firestore/core/test/firebase/firestore/util/async_queue_test.h @@ -28,7 +28,7 @@ namespace firebase { namespace firestore { namespace util { -using FactoryFunc = std::unique_ptr (*)(); +using FactoryFunc = std::unique_ptr (*)(); class AsyncQueueTest : public TestWithTimeoutMixin, public ::testing::TestWithParam { diff --git a/Firestore/core/test/firebase/firestore/util/executor_libdispatch_test.mm b/Firestore/core/test/firebase/firestore/util/executor_libdispatch_test.mm index 376247b6832..939521df003 100644 --- a/Firestore/core/test/firebase/firestore/util/executor_libdispatch_test.mm +++ b/Firestore/core/test/firebase/firestore/util/executor_libdispatch_test.mm @@ -28,8 +28,8 @@ namespace { -std::unique_ptr ExecutorFactory() { - return absl::make_unique( +std::unique_ptr ExecutorFactory() { + return absl::make_unique( dispatch_queue_create("ExecutorLibdispatchTests", DISPATCH_QUEUE_SERIAL)); } diff --git a/Firestore/core/test/firebase/firestore/util/executor_std_test.cc b/Firestore/core/test/firebase/firestore/util/executor_std_test.cc index 59c3c32f570..84c0495f950 100644 --- a/Firestore/core/test/firebase/firestore/util/executor_std_test.cc +++ b/Firestore/core/test/firebase/firestore/util/executor_std_test.cc @@ -229,8 +229,8 @@ TEST_F(ScheduleTest, PopBlockingIsNotAffectedByIrrelevantRemovals) { namespace { -inline std::unique_ptr ExecutorFactory() { - return absl::make_unique(); +inline std::unique_ptr ExecutorFactory() { + return absl::make_unique(); } } // namespace diff --git a/Firestore/core/test/firebase/firestore/util/executor_test.cc b/Firestore/core/test/firebase/firestore/util/executor_test.cc index e983bfe3a29..98ae677c628 100644 --- a/Firestore/core/test/firebase/firestore/util/executor_test.cc +++ b/Firestore/core/test/firebase/firestore/util/executor_test.cc @@ -30,7 +30,6 @@ namespace firestore { namespace util { namespace chr = std::chrono; -using internal::Executor; namespace { diff --git a/Firestore/core/test/firebase/firestore/util/executor_test.h b/Firestore/core/test/firebase/firestore/util/executor_test.h index 8b78d5023af..88b5cb02052 100644 --- a/Firestore/core/test/firebase/firestore/util/executor_test.h +++ b/Firestore/core/test/firebase/firestore/util/executor_test.h @@ -28,7 +28,7 @@ namespace firebase { namespace firestore { namespace util { -using FactoryFunc = std::unique_ptr (*)(); +using FactoryFunc = std::unique_ptr (*)(); class ExecutorTest : public TestWithTimeoutMixin, public ::testing::TestWithParam { @@ -37,7 +37,7 @@ class ExecutorTest : public TestWithTimeoutMixin, ExecutorTest() : executor{GetParam()()} { } - std::unique_ptr executor; + std::unique_ptr executor; }; } // namespace util } // namespace firestore diff --git a/Firestore/core/test/firebase/firestore/util/grpc_stream_tester.cc b/Firestore/core/test/firebase/firestore/util/grpc_stream_tester.cc index 0595f52c0ab..f5ab581877b 100644 --- a/Firestore/core/test/firebase/firestore/util/grpc_stream_tester.cc +++ b/Firestore/core/test/firebase/firestore/util/grpc_stream_tester.cc @@ -31,7 +31,6 @@ namespace util { using auth::Token; using auth::User; -using internal::ExecutorStd; using model::DatabaseId; using remote::ConnectivityMonitor; using remote::GrpcCompletion; diff --git a/Firestore/core/test/firebase/firestore/util/grpc_stream_tester.h b/Firestore/core/test/firebase/firestore/util/grpc_stream_tester.h index 3b242501f15..d9c179743df 100644 --- a/Firestore/core/test/firebase/firestore/util/grpc_stream_tester.h +++ b/Firestore/core/test/firebase/firestore/util/grpc_stream_tester.h @@ -118,7 +118,7 @@ class FakeGrpcQueue { private: remote::GrpcCompletion* ExtractCompletion(); - std::unique_ptr dedicated_executor_; + std::unique_ptr dedicated_executor_; grpc::CompletionQueue* grpc_queue_; bool is_shut_down_ = false;