diff --git a/Firestore/Example/Firestore.xcodeproj/xcshareddata/xcschemes/Firestore_IntegrationTests_iOS.xcscheme b/Firestore/Example/Firestore.xcodeproj/xcshareddata/xcschemes/Firestore_IntegrationTests_iOS.xcscheme index bae10f26115..08b9daf7407 100644 --- a/Firestore/Example/Firestore.xcodeproj/xcshareddata/xcschemes/Firestore_IntegrationTests_iOS.xcscheme +++ b/Firestore/Example/Firestore.xcodeproj/xcshareddata/xcschemes/Firestore_IntegrationTests_iOS.xcscheme @@ -27,6 +27,7 @@ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" shouldUseLaunchSchemeArgsEnv = "YES" + enableAddressSanitizer = "YES" enableASanStackUseAfterReturn = "YES"> + + + + diff --git a/Firestore/Source/API/FIRCallbackWrapper.mm b/Firestore/Source/API/FIRCallbackWrapper.mm index 68275613b5d..2eb3e417bc7 100644 --- a/Firestore/Source/API/FIRCallbackWrapper.mm +++ b/Firestore/Source/API/FIRCallbackWrapper.mm @@ -16,6 +16,7 @@ #import "FIRCallbackWrapper.h" +#include #include #include #include @@ -35,21 +36,24 @@ @implementation FIRCallbackWrapper + (PipelineSnapshotListener)wrapPipelineCallback:(std::shared_ptr)firestore - completion:(void (^)(PipelineResultVector result, + completion:(void (^)(CppPipelineResult *result, NSError *_Nullable error))completion { - class Converter : public EventListener> { + class Converter : public EventListener { public: explicit Converter(std::shared_ptr firestore, PipelineBlock completion) : firestore_(firestore), completion_(completion) { } - void OnEvent(StatusOr> maybe_snapshot) override { + void OnEvent(StatusOr maybe_snapshot) override { if (maybe_snapshot.ok()) { - completion_( - std::initializer_list{PipelineResult::GetTestResult(firestore_)}, - nullptr); + std::cout << "zzyzx OnEvent 1" << std::endl; + CppPipelineResult result = maybe_snapshot.ValueOrDie(); + std::cout << "zzyzx OnEvent 2 result.id=" << result.id_ << std::endl; + completion_(&result, nullptr); + std::cout << "zzyzx OnEvent 3 result.id=" << result.id_ << std::endl; } else { - completion_(std::initializer_list{}, MakeNSError(maybe_snapshot.status())); + // completion_(PipelineResult::GetTestResult(firestore_), + // MakeNSError(maybe_snapshot.status())); } } @@ -58,7 +62,7 @@ void OnEvent(StatusOr> maybe_snapshot) override { PipelineBlock completion_; }; - return absl::make_unique(firestore, completion); + return std::make_shared(firestore, completion); } @end diff --git a/Firestore/Source/Public/FirebaseFirestore/FIRCallbackWrapper.h b/Firestore/Source/Public/FirebaseFirestore/FIRCallbackWrapper.h index 08a9b9713dd..4cecd248fd4 100644 --- a/Firestore/Source/Public/FirebaseFirestore/FIRCallbackWrapper.h +++ b/Firestore/Source/Public/FirebaseFirestore/FIRCallbackWrapper.h @@ -38,10 +38,10 @@ namespace core = firebase::firestore::core; NS_ASSUME_NONNULL_BEGIN -typedef void (^PipelineBlock)(std::vector result, NSError *_Nullable error) - NS_SWIFT_UNAVAILABLE("Use Swift's closure syntax instead."); +typedef api::PipelineResult CppPipelineResult; -typedef std::vector PipelineResultVector; +typedef void (^PipelineBlock)(CppPipelineResult *result, NSError *_Nullable error) + NS_SWIFT_UNAVAILABLE("Use Swift's closure syntax instead."); NS_SWIFT_SENDABLE NS_SWIFT_NAME(CallbackWrapper) @@ -51,9 +51,9 @@ NS_SWIFT_NAME(CallbackWrapper) // are invoked on a different thread than the one they were originally defined in. If this callback // is expected to be called on a different thread, it should be marked as `Sendable` to ensure // thread safety. -+ (std::shared_ptr>>) ++ (std::shared_ptr>) wrapPipelineCallback:(std::shared_ptr)firestore - completion:(void (^NS_SWIFT_SENDABLE)(PipelineResultVector result, + completion:(void (^NS_SWIFT_SENDABLE)(CppPipelineResult *result, NSError *_Nullable error))completion NS_SWIFT_NAME(wrapPipelineCallback(firestore:completion:)); diff --git a/Firestore/Swift/Source/SwiftAPI/Pipeline.swift b/Firestore/Swift/Source/SwiftAPI/Pipeline.swift index 26e1e342783..234555d1116 100644 --- a/Firestore/Swift/Source/SwiftAPI/Pipeline.swift +++ b/Firestore/Swift/Source/SwiftAPI/Pipeline.swift @@ -29,7 +29,7 @@ public struct Pipeline { } @discardableResult - public func GetPipelineResult() async throws -> [PipelineResult] { + public func GetPipelineResult() async throws -> Int { return try await withCheckedThrowingContinuation { continuation in let listener = CallbackWrapper.wrapPipelineCallback(firestore: cppObj.GetFirestore()) { result, error in @@ -37,7 +37,9 @@ public struct Pipeline { continuation.resume(throwing: error) } else { // Our callbacks guarantee that we either return an error or a progress event. - continuation.resume(returning: PipelineResult.convertToArrayFromCppVector(result)) + print("zzyzx Swift use id: \(result.pointee.id_)") + PipelineResult(result.pointee) + continuation.resume(returning: 5) } } cppObj.GetPipelineResult(listener) diff --git a/Firestore/Swift/Source/SwiftAPI/PipelineResult.swift b/Firestore/Swift/Source/SwiftAPI/PipelineResult.swift index 0e084f4a4af..396335b0951 100644 --- a/Firestore/Swift/Source/SwiftAPI/PipelineResult.swift +++ b/Firestore/Swift/Source/SwiftAPI/PipelineResult.swift @@ -22,17 +22,18 @@ public struct PipelineResult { public init(_ cppSource: firebase.firestore.api.PipelineResult) { cppObj = cppSource + print("zzyzx SwiftObj id: \(cppObj.id_)") } - static func convertToArrayFromCppVector(_ vector: PipelineResultVector) + static func convertToArrayFromCppVector(_ vector: CppPipelineResult) -> [PipelineResult] { // Create a Swift array and populate it by iterating over the C++ vector var swiftArray: [PipelineResult] = [] - for index in vector.indices { - let cppResult = vector[index] - swiftArray.append(PipelineResult(cppResult)) - } +// for index in vector.indices { +// let cppResult = vector[index] +// swiftArray.append(PipelineResult(cppResult)) +// } return swiftArray } diff --git a/Firestore/Swift/Tests/Integration/PipelineTests.swift b/Firestore/Swift/Tests/Integration/PipelineTests.swift index ff12c519f66..26f4c89716a 100644 --- a/Firestore/Swift/Tests/Integration/PipelineTests.swift +++ b/Firestore/Swift/Tests/Integration/PipelineTests.swift @@ -21,6 +21,6 @@ final class PipelineTests: FSTIntegrationTestCase { func testCreatePipeline() async throws { let pipelineSource: PipelineSource = db.pipeline() let pipeline: Pipeline = pipelineSource.GetCollection("path") - let _: [PipelineResult] = try await pipeline.GetPipelineResult() + let _ = try await pipeline.GetPipelineResult() } } diff --git a/Firestore/core/interfaceForSwift/api/pipeline.cc b/Firestore/core/interfaceForSwift/api/pipeline.cc index c1da06de449..c090857e0f2 100644 --- a/Firestore/core/interfaceForSwift/api/pipeline.cc +++ b/Firestore/core/interfaceForSwift/api/pipeline.cc @@ -45,8 +45,10 @@ void Pipeline::GetPipelineResult(PipelineSnapshotListener callback) const { /*include_document_metadata_changes=*/true, /*wait_for_sync_when_online=*/true); - callback->OnEvent(StatusOr>( - {(PipelineResult::GetTestResult(firestore_))})); + PipelineResult sample = PipelineResult::GetTestResult(firestore_); + + StatusOr res(sample); + callback->OnEvent(res); // class ListenOnce : public EventListener> { // public: diff --git a/Firestore/core/interfaceForSwift/api/pipeline.h b/Firestore/core/interfaceForSwift/api/pipeline.h index ff963af0efe..2cc7fef45e8 100644 --- a/Firestore/core/interfaceForSwift/api/pipeline.h +++ b/Firestore/core/interfaceForSwift/api/pipeline.h @@ -35,7 +35,7 @@ class Firestore; class PipelineResult; using PipelineSnapshotListener = - std::shared_ptr>>; + std::shared_ptr>; class Pipeline { public: diff --git a/Firestore/core/interfaceForSwift/api/pipeline_result.cc b/Firestore/core/interfaceForSwift/api/pipeline_result.cc index 7851c9aeeb8..309693ae319 100644 --- a/Firestore/core/interfaceForSwift/api/pipeline_result.cc +++ b/Firestore/core/interfaceForSwift/api/pipeline_result.cc @@ -12,22 +12,29 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "Firestore/core/interfaceForSwift/api/pipeline_result.h" +#include + #include "Firestore/core/include/firebase/firestore/timestamp.h" +#include "Firestore/core/interfaceForSwift/api/pipeline_result.h" namespace firebase { namespace firestore { namespace api { +std::atomic next_id(0); + PipelineResult::PipelineResult(std::shared_ptr firestore, std::shared_ptr execution_time, std::shared_ptr update_time, std::shared_ptr create_time) - : firestore_(firestore), + : id_(next_id.fetch_add(1)), + firestore_(firestore), execution_time_(execution_time), update_time_(update_time), create_time_(create_time) { + std::cout << "zzyzx PipelineResult[" << id_ << "]@" + << reinterpret_cast(this) << "()" << std::endl; } PipelineResult PipelineResult::GetTestResult( diff --git a/Firestore/core/interfaceForSwift/api/pipeline_result.h b/Firestore/core/interfaceForSwift/api/pipeline_result.h index 10488aa9557..815a2e4408a 100644 --- a/Firestore/core/interfaceForSwift/api/pipeline_result.h +++ b/Firestore/core/interfaceForSwift/api/pipeline_result.h @@ -15,6 +15,8 @@ #ifndef FIRESTORE_CORE_INTERFACEFORSWIFT_API_PIPELINE_RESULT_H_ #define FIRESTORE_CORE_INTERFACEFORSWIFT_API_PIPELINE_RESULT_H_ +#include +#include #include namespace firebase { @@ -28,6 +30,8 @@ namespace api { class Firestore; class DocumentReference; +extern std::atomic next_id; + class PipelineResult { public: PipelineResult(std::shared_ptr firestore, @@ -35,9 +39,46 @@ class PipelineResult { std::shared_ptr update_time, std::shared_ptr create_time); + // Copy constructor + PipelineResult(const PipelineResult& other) + : id_(next_id.fetch_add(1)), + firestore_(other.firestore_), + execution_time_(other.execution_time_), + update_time_(other.update_time_), + create_time_(other.create_time_) { + std::cout << "zzyzx PipelineResult[" << id_ << "]@" + << reinterpret_cast(this) + << "(const PipelineResult&) other.id=" << other.id_ << std::endl; + long n = execution_time_.use_count(); + std::cout << "Calling copy ctor when refer count is:" << n << std::endl; + } + + // Copy assignment operator + PipelineResult& operator=(const PipelineResult& other) { + std::cout << "zzyzx PipelineResult[" << id_ << "]@" + << reinterpret_cast(this) + << ".operator=(const PipelineResult&) other.id_=" << other.id_ + << std::endl; + if (this != &other) { + firestore_ = other.firestore_; + execution_time_ = other.execution_time_; + update_time_ = other.update_time_; + create_time_ = other.create_time_; + } + return *this; + } + static PipelineResult GetTestResult(std::shared_ptr firestore); - private: + ~PipelineResult() { + std::cout << "zzyzx PipelineResult[" << id_ << "]@" + << reinterpret_cast(this) << "~PipelineResult()" + << std::endl; + long n = execution_time_.use_count(); + std::cout << "Calling destructor when refer count is:" << n << std::endl; + } + + int id_; std::shared_ptr firestore_; std::shared_ptr execution_time_; std::shared_ptr update_time_;