From e10e13fa236a7a8ce0c6e6723f87d40e3174f027 Mon Sep 17 00:00:00 2001 From: Kyle Date: Sun, 31 Aug 2025 16:09:59 +0800 Subject: [PATCH 1/5] Update OAGUniqueID --- Sources/OpenAttributeGraphCxx/Data/OAGUniqueID.c | 7 +++---- .../include/OpenAttributeGraph/OAGUniqueID.h | 4 ++-- Sources/OpenAttributeGraphShims/GraphShims.swift | 1 - .../OpenAttributeGraphCompatibilityTests/GraphShims.swift | 1 - 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/Sources/OpenAttributeGraphCxx/Data/OAGUniqueID.c b/Sources/OpenAttributeGraphCxx/Data/OAGUniqueID.c index 94a92b62..05911270 100644 --- a/Sources/OpenAttributeGraphCxx/Data/OAGUniqueID.c +++ b/Sources/OpenAttributeGraphCxx/Data/OAGUniqueID.c @@ -2,14 +2,13 @@ // OAGUniqueID.c // OpenAttributeGraphCxx // -// Audited for iOS 18.0 +// Audited for 6.5.1 // Status: Complete #include #include OAGUniqueID OAGMakeUniqueID(void) { - // Initial value is 1 - static atomic_long counter = 1; - return counter++; + static atomic_ulong counter = 1; + return atomic_fetch_add_explicit(&counter, 1, memory_order_relaxed); } diff --git a/Sources/OpenAttributeGraphCxx/include/OpenAttributeGraph/OAGUniqueID.h b/Sources/OpenAttributeGraphCxx/include/OpenAttributeGraph/OAGUniqueID.h index 9a906b51..94be328f 100644 --- a/Sources/OpenAttributeGraphCxx/include/OpenAttributeGraph/OAGUniqueID.h +++ b/Sources/OpenAttributeGraphCxx/include/OpenAttributeGraph/OAGUniqueID.h @@ -2,14 +2,14 @@ // OAGUniqueID.h // OpenAttributeGraphCxx // -// Audited for iOS 18.0 +// Audited for 6.5.1 // Status: Complete #ifndef OAGUniqueID_h #define OAGUniqueID_h #include -typedef long OAGUniqueID; +typedef u_long OAGUniqueID OAG_SWIFT_NAME(UniqueID); OAG_EXTERN_C_BEGIN OAG_EXPORT diff --git a/Sources/OpenAttributeGraphShims/GraphShims.swift b/Sources/OpenAttributeGraphShims/GraphShims.swift index 41b0abde..c02e82af 100644 --- a/Sources/OpenAttributeGraphShims/GraphShims.swift +++ b/Sources/OpenAttributeGraphShims/GraphShims.swift @@ -8,7 +8,6 @@ public typealias OAGAttributeInfo = AGAttributeInfo public typealias OAGCachedValueOptions = AGCachedValueOptions public typealias OAGChangedValueFlags = AGChangedValueFlags public typealias OAGInputOptions = AGInputOptions -public typealias OAGUniqueID = AGUniqueID public typealias OAGValue = AGValue public typealias OAGValueOptions = AGValueOptions public let attributeGraphEnabled = true diff --git a/Tests/OpenAttributeGraphCompatibilityTests/GraphShims.swift b/Tests/OpenAttributeGraphCompatibilityTests/GraphShims.swift index 2c2cdc04..43dccc9b 100644 --- a/Tests/OpenAttributeGraphCompatibilityTests/GraphShims.swift +++ b/Tests/OpenAttributeGraphCompatibilityTests/GraphShims.swift @@ -8,7 +8,6 @@ public typealias OAGAttributeInfo = AGAttributeInfo public typealias OAGCachedValueOptions = AGCachedValueOptions public typealias OAGChangedValueFlags = AGChangedValueFlags public typealias OAGInputOptions = AGInputOptions -public typealias OAGUniqueID = AGUniqueID public typealias OAGValue = AGValue public typealias OAGValueOptions = AGValueOptions public let compatibilityTestEnabled = true From 7efb3e79251226db222c4cbce2bab8d1352d11d2 Mon Sep 17 00:00:00 2001 From: Kyle Date: Sun, 31 Aug 2025 16:12:24 +0800 Subject: [PATCH 2/5] Update addObserver and add removeObserver for Subgraph --- .../OpenAttributeGraph/Graph/Subgraph.swift | 4 +- .../Graph/OAGSubgraph.cpp | 10 +- .../OpenAttributeGraphCxx/Graph/Subgraph.cpp | 4 + .../OpenAttributeGraphCxx/Graph/Subgraph.hpp | 109 ------------------ .../include/OpenAttributeGraph/OAGSubgraph.h | 8 +- .../OpenAttributeGraphCxx/Graph/Subgraph.hpp | 3 +- .../Graph/SubgraphCompatibilityTests.swift | 55 +++++++++ 7 files changed, 79 insertions(+), 114 deletions(-) delete mode 100644 Sources/OpenAttributeGraphCxx/Graph/Subgraph.hpp diff --git a/Sources/OpenAttributeGraph/Graph/Subgraph.swift b/Sources/OpenAttributeGraph/Graph/Subgraph.swift index f66108a1..4d2b952e 100644 --- a/Sources/OpenAttributeGraph/Graph/Subgraph.swift +++ b/Sources/OpenAttributeGraph/Graph/Subgraph.swift @@ -15,7 +15,7 @@ extension Subgraph { } extension Subgraph { - public func addObserver(_ observer: () -> Void) -> Int { + public func addObserver(_ observer: @escaping () -> Void) -> Int { Subgraph.addObserver(self, observer: observer) } @@ -65,5 +65,5 @@ extension Subgraph { private static func apply(_ graph: Subgraph, flags: Flags, callback: (AnyAttribute) -> Void) @_silgen_name("OAGSubgraphAddObserver") - private static func addObserver(_ graph: Subgraph, observer: () -> Void) -> Int + private static func addObserver(_ graph: Subgraph, observer: @escaping () -> Void) -> Int } diff --git a/Sources/OpenAttributeGraphCxx/Graph/OAGSubgraph.cpp b/Sources/OpenAttributeGraphCxx/Graph/OAGSubgraph.cpp index 006dcc69..45896a47 100644 --- a/Sources/OpenAttributeGraphCxx/Graph/OAGSubgraph.cpp +++ b/Sources/OpenAttributeGraphCxx/Graph/OAGSubgraph.cpp @@ -163,7 +163,7 @@ bool OAGSubgraphIsDirty(OAGSubgraphRef cf_subgraph, OAGAttributeFlags flags) { return false; } -OAGUniqueID OAGSubgraphAddObserver(OAGSubgraphRef cf_subgraph, +OAGObserverID OAGSubgraphAddObserver(OAGSubgraphRef cf_subgraph, const void (*function)(const void * _Nullable context OAG_SWIFT_CONTEXT) OAG_SWIFT_CC(swift), const void * _Nullable context) { OAG::Subgraph *subgraph = cf_subgraph->subgraph; @@ -173,6 +173,14 @@ OAGUniqueID OAGSubgraphAddObserver(OAGSubgraphRef cf_subgraph, return subgraph->add_observer(OAG::ClosureFunction(function, context)); } +void OAGSubgraphRemoveObserver(OAGSubgraphRef cf_subgraph, OAGObserverID observerID) { + OAG::Subgraph *subgraph = cf_subgraph->subgraph; + if (subgraph == nullptr) { + return; + } + subgraph->remove_observer(observerID); +} + #if !OAG_TARGET_OS_WASI static bool should_record_tree; static dispatch_once_t should_record_tree_once; diff --git a/Sources/OpenAttributeGraphCxx/Graph/Subgraph.cpp b/Sources/OpenAttributeGraphCxx/Graph/Subgraph.cpp index 1c7cdc16..4083744c 100644 --- a/Sources/OpenAttributeGraphCxx/Graph/Subgraph.cpp +++ b/Sources/OpenAttributeGraphCxx/Graph/Subgraph.cpp @@ -34,6 +34,10 @@ OAGUniqueID OAG::Subgraph::add_observer(OAG::ClosureFunction observer) con return OAGMakeUniqueID(); } +void OAG::Subgraph::remove_observer(OAGUniqueID observerID) const OAG_NOEXCEPT { + // TODO +} + void OAG::Subgraph::begin_tree(OAG::AttributeID id, OAG::swift::metadata const* type, unsigned int flags) const OAG_NOEXCEPT { // TODO } diff --git a/Sources/OpenAttributeGraphCxx/Graph/Subgraph.hpp b/Sources/OpenAttributeGraphCxx/Graph/Subgraph.hpp deleted file mode 100644 index 60fa4458..00000000 --- a/Sources/OpenAttributeGraphCxx/Graph/Subgraph.hpp +++ /dev/null @@ -1,109 +0,0 @@ -// -// Subgraph.hpp -// OpenAttributeGraphCxx - -#ifndef Subgraph_hpp -#define Subgraph_hpp - -#include "OAGBase.h" -#include -#include -#include -#include -#include - -typedef struct OAG_BRIDGED_TYPE(id) OAGSubgraphStorage * OAGSubgraphRef; - -namespace OAG { -class SubgraphObject; - -class Subgraph final { -private: - OAGSubgraphRef _cf_subgraph; - OAGGraphContextStorage& _context; - // TODO - bool _isInvalid; - static pthread_key_t _current_subgraph_key; -public: - // MARK: - CF related - - static Subgraph *from_cf(OAGSubgraphRef cf_subgraph) OAG_NOEXCEPT; - - OAGSubgraphRef to_cf() const OAG_NOEXCEPT { - return _cf_subgraph; - } - - // MARK: - pthread related - - OAG_INLINE - const static void make_current_subgraph_key() OAG_NOEXCEPT { - pthread_key_create(&_current_subgraph_key, nullptr); - } - - OAG_INLINE OAG_CONSTEXPR - const static pthread_key_t& current_key() OAG_NOEXCEPT { - return _current_subgraph_key; - } - - OAG_INLINE OAG_CONSTEXPR - static Subgraph *get_current() OAG_NOEXCEPT { - return (OAG::Subgraph*)pthread_getspecific(OAG::Subgraph::current_key()); - } - - OAG_INLINE OAG_CONSTEXPR - static int set_current(Subgraph *subgraph) OAG_NOEXCEPT { - return pthread_setspecific(OAG::Subgraph::current_key(), subgraph); - } - - // MARK: - Public API - void clear_object() const OAG_NOEXCEPT; - void invalidate_and_delete_(bool) const OAG_NOEXCEPT; - - void apply(OAGAttributeFlags flags, OAG::ClosureFunction body) const OAG_NOEXCEPT; - - OAGUniqueID add_observer(OAG::ClosureFunction observer) const OAG_NOEXCEPT; - - void begin_tree(OAG::AttributeID id, OAG::swift::metadata const *type, uint32_t flags) const OAG_NOEXCEPT; - void add_tree_value(OAG::AttributeID id, OAG::swift::metadata const *type, const char* key, uint32_t flags) const OAG_NOEXCEPT; - void end_tree(OAG::AttributeID id) const OAG_NOEXCEPT; - - // MARK: - Init and deinit - - Subgraph(SubgraphObject*, OAG::Graph::Context&, OAG::AttributeID); - - // MARK: - Getter and setter - - OAG_INLINE OAG_CONSTEXPR - const OAGGraphContextRef get_context() const OAG_NOEXCEPT { - return &_context; - } - - OAG_INLINE OAG_CONSTEXPR - OAGGraphContextRef get_context() OAG_NOEXCEPT { - return &_context; - } - - OAG_INLINE OAG_CONSTEXPR - const bool isInvalid() const OAG_NOEXCEPT { - return _isInvalid; - } - - OAG_INLINE OAG_CONSTEXPR - void setInvalid(bool invalid) OAG_NOEXCEPT { - _isInvalid = invalid; - } -}; /* Subgraph */ -} /* OAG */ - -struct OAGSubgraphStorage { - CFRuntimeBase base; - OAG::Subgraph *subgraph; -}; - -namespace OAG { -class SubgraphObject final { - OAGSubgraphStorage storage; -}; -} - -#endif /* Subgraph_hpp */ diff --git a/Sources/OpenAttributeGraphCxx/include/OpenAttributeGraph/OAGSubgraph.h b/Sources/OpenAttributeGraphCxx/include/OpenAttributeGraph/OAGSubgraph.h index 84c6386e..a6558360 100644 --- a/Sources/OpenAttributeGraphCxx/include/OpenAttributeGraph/OAGSubgraph.h +++ b/Sources/OpenAttributeGraphCxx/include/OpenAttributeGraph/OAGSubgraph.h @@ -87,12 +87,18 @@ OAG_EXPORT OAG_REFINED_FOR_SWIFT bool OAGSubgraphIsDirty(OAGSubgraphRef cf_subgraph, OAGAttributeFlags flags) OAG_SWIFT_NAME(OAGSubgraphRef.isDirty(self:flags:)); +typedef long OAGObserverID OAG_SWIFT_NAME(ObserverID); + OAG_EXPORT OAG_REFINED_FOR_SWIFT -OAGUniqueID OAGSubgraphAddObserver(OAGSubgraphRef cf_subgraph, +OAGObserverID OAGSubgraphAddObserver(OAGSubgraphRef cf_subgraph, const void (*function)(const void * _Nullable context OAG_SWIFT_CONTEXT) OAG_SWIFT_CC(swift), const void * _Nullable context); +OAG_EXPORT +OAG_REFINED_FOR_SWIFT +void OAGSubgraphRemoveObserver(OAGSubgraphRef cf_subgraph, OAGObserverID observerID) OAG_SWIFT_NAME(OAGSubgraphRef.removeObserver(self:_:)); + OAG_EXPORT OAG_REFINED_FOR_SWIFT bool OAGSubgraphShouldRecordTree(void) OAG_SWIFT_NAME(getter:OAGSubgraphRef.shouldRecordTree()); diff --git a/Sources/OpenAttributeGraphCxx/include/OpenAttributeGraphCxx/Graph/Subgraph.hpp b/Sources/OpenAttributeGraphCxx/include/OpenAttributeGraphCxx/Graph/Subgraph.hpp index b1d6eb37..a798d8c0 100644 --- a/Sources/OpenAttributeGraphCxx/include/OpenAttributeGraphCxx/Graph/Subgraph.hpp +++ b/Sources/OpenAttributeGraphCxx/include/OpenAttributeGraphCxx/Graph/Subgraph.hpp @@ -62,7 +62,8 @@ class Subgraph final { void apply(OAGAttributeFlags flags, OAG::ClosureFunction body) const OAG_NOEXCEPT; OAGUniqueID add_observer(OAG::ClosureFunction observer) const OAG_NOEXCEPT; - + void remove_observer(OAGUniqueID observerID) const OAG_NOEXCEPT; + void begin_tree(OAG::AttributeID id, OAG::swift::metadata const *type, uint32_t flags) const OAG_NOEXCEPT; void add_tree_value(OAG::AttributeID id, OAG::swift::metadata const *type, const char* key, uint32_t flags) const OAG_NOEXCEPT; void end_tree(OAG::AttributeID id) const OAG_NOEXCEPT; diff --git a/Tests/OpenAttributeGraphCompatibilityTests/Graph/SubgraphCompatibilityTests.swift b/Tests/OpenAttributeGraphCompatibilityTests/Graph/SubgraphCompatibilityTests.swift index 20b44e60..cce7c347 100644 --- a/Tests/OpenAttributeGraphCompatibilityTests/Graph/SubgraphCompatibilityTests.swift +++ b/Tests/OpenAttributeGraphCompatibilityTests/Graph/SubgraphCompatibilityTests.swift @@ -28,4 +28,59 @@ struct SubgraphCompatibilityTests { Subgraph.endTreeElement(value: value) } } + + @Suite + struct ObserverTests { + @Test + func observerNotifiedOnSubgraphDestroyed() { + var notifiedCount = 0 + autoreleasepool { + let graph = Graph() + + autoreleasepool { + let subgraph = Subgraph(graph: graph) + let _ = subgraph.addObserver { + notifiedCount += 1 + } + } + + #expect(notifiedCount == 1) + } + + // Observers aren't notified more than once + #expect(notifiedCount == 1) + } + + @Test + func observerNotifiedOnGraphDestroyed() { + var notifiedCount = 0 + autoreleasepool { + let graph = Graph() + let subgraph = Subgraph(graph: graph) + let _ = subgraph.addObserver { + notifiedCount += 1 + } + + #expect(notifiedCount == 0) + } + + #expect(notifiedCount == 1) + } + + @Test + func removedObserverNotNotified() { + var notifiedCount = 0 + autoreleasepool { + let graph = Graph() + let subgraph = Subgraph(graph: graph) + let observerID = subgraph.addObserver { + notifiedCount += 1 + } + subgraph.removeObserver(observerID) + } + + #expect(notifiedCount == 0) + } + + } } From 8b748377352c06ec7f41c44368428edab5a28bd4 Mon Sep 17 00:00:00 2001 From: Kyle Date: Sun, 31 Aug 2025 16:17:36 +0800 Subject: [PATCH 3/5] Add OAGGraphGetAttributeSubgraph2 --- .../Attribute/OAGAttribute.cpp | 15 +++++++++++++++ .../include/OpenAttributeGraph/OAGAttribute.h | 4 ++++ 2 files changed, 19 insertions(+) diff --git a/Sources/OpenAttributeGraphCxx/Attribute/OAGAttribute.cpp b/Sources/OpenAttributeGraphCxx/Attribute/OAGAttribute.cpp index 79f7fc9d..f32391aa 100644 --- a/Sources/OpenAttributeGraphCxx/Attribute/OAGAttribute.cpp +++ b/Sources/OpenAttributeGraphCxx/Attribute/OAGAttribute.cpp @@ -159,6 +159,21 @@ OAGGraphRef OAGGraphGetAttributeGraph(OAGAttribute attribute) { } OAGSubgraphRef OAGGraphGetAttributeSubgraph(OAGAttribute attribute) { + OAGSubgraphRef subgraph = OAGGraphGetAttributeSubgraph2(attribute); + if (subgraph == nullptr) { + OAG::precondition_failure("no subgraph"); + } + return subgraph; +} + +_Nullable OAGSubgraphRef OAGGraphGetAttributeSubgraph2(OAGAttribute attribute) { + auto attribute_id = OAG::AttributeID(attribute); +// attribute_id.validate_data_offset(); +// auto subgraph = attribute_id.subgraph(); +// if (subgraph == nullptr) { +// OAG::precondition_failure("internal error"); +// } +// return subgraph->to_cf(); // TODO return nullptr; } diff --git a/Sources/OpenAttributeGraphCxx/include/OpenAttributeGraph/OAGAttribute.h b/Sources/OpenAttributeGraphCxx/include/OpenAttributeGraph/OAGAttribute.h index 1e9786c7..27e39d94 100644 --- a/Sources/OpenAttributeGraphCxx/include/OpenAttributeGraph/OAGAttribute.h +++ b/Sources/OpenAttributeGraphCxx/include/OpenAttributeGraph/OAGAttribute.h @@ -139,6 +139,10 @@ OAG_EXPORT OAG_REFINED_FOR_SWIFT OAGSubgraphRef OAGGraphGetAttributeSubgraph(OAGAttribute attribute) OAG_SWIFT_NAME(getter:OAGAttribute.subgraph(self:)); +OAG_EXPORT +OAG_REFINED_FOR_SWIFT +_Nullable OAGSubgraphRef OAGGraphGetAttributeSubgraph2(OAGAttribute attribute) OAG_SWIFT_NAME(getter:OAGAttribute.subgraph2(self:)); + OAG_EXPORT OAG_REFINED_FOR_SWIFT const void * OAGGraphReadCachedAttribute(long hashValue, OAGTypeID bodyType, const void *bodyPointer, OAGTypeID valueType, OAGCachedValueOptions options, OAGAttribute attribute, bool unknown/*, ...*/); From aebb6e1e134fdf9d9c85212a27ffc9276da5a32a Mon Sep 17 00:00:00 2001 From: Kyle Date: Sun, 31 Aug 2025 16:21:18 +0800 Subject: [PATCH 4/5] Bump DarwinPrivateFrameworks dependency See https://github.com/OpenSwiftUIProject/DarwinPrivateFrameworks/pull/14 --- Package.resolved | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Package.resolved b/Package.resolved index 371bd739..d1499cd8 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "7ad3e8511a63915009dd025ffe4d701d034989c2468ac56c7d063a0c962dca4b", + "originHash" : "9fc132d8a2914e41367e55e17402381d2909fd00acd94ebc8bdb4ecf8809f175", "pins" : [ { "identity" : "darwinprivateframeworks", @@ -7,7 +7,7 @@ "location" : "https://github.com/OpenSwiftUIProject/DarwinPrivateFrameworks.git", "state" : { "branch" : "main", - "revision" : "4aa30d65aae91b8cd3aa7e6b5910d281a77e9af0" + "revision" : "fdb349e4715fafdb847852e03c414739b21ae8b8" } }, { From 77a1f8f96ef3cdc7c59daac88ab080c566ebfc99 Mon Sep 17 00:00:00 2001 From: Kyle Date: Sun, 31 Aug 2025 16:39:44 +0800 Subject: [PATCH 5/5] Fix Ubuntu CI build by replacing autoreleasepool with do blocks Replace autoreleasepool blocks with do blocks in SubgraphCompatibilityTests to fix build failures on Ubuntu/Linux where autoreleasepool is not available (Darwin-only feature). The do blocks maintain the same scoping behavior needed for the tests while being cross-platform compatible. --- .../Graph/SubgraphCompatibilityTests.swift | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/Tests/OpenAttributeGraphCompatibilityTests/Graph/SubgraphCompatibilityTests.swift b/Tests/OpenAttributeGraphCompatibilityTests/Graph/SubgraphCompatibilityTests.swift index cce7c347..b08dd697 100644 --- a/Tests/OpenAttributeGraphCompatibilityTests/Graph/SubgraphCompatibilityTests.swift +++ b/Tests/OpenAttributeGraphCompatibilityTests/Graph/SubgraphCompatibilityTests.swift @@ -34,19 +34,16 @@ struct SubgraphCompatibilityTests { @Test func observerNotifiedOnSubgraphDestroyed() { var notifiedCount = 0 - autoreleasepool { + do { let graph = Graph() - - autoreleasepool { + do { let subgraph = Subgraph(graph: graph) let _ = subgraph.addObserver { notifiedCount += 1 } } - #expect(notifiedCount == 1) } - // Observers aren't notified more than once #expect(notifiedCount == 1) } @@ -54,23 +51,21 @@ struct SubgraphCompatibilityTests { @Test func observerNotifiedOnGraphDestroyed() { var notifiedCount = 0 - autoreleasepool { + do { let graph = Graph() let subgraph = Subgraph(graph: graph) let _ = subgraph.addObserver { notifiedCount += 1 } - #expect(notifiedCount == 0) } - #expect(notifiedCount == 1) } @Test func removedObserverNotNotified() { var notifiedCount = 0 - autoreleasepool { + do { let graph = Graph() let subgraph = Subgraph(graph: graph) let observerID = subgraph.addObserver { @@ -78,9 +73,7 @@ struct SubgraphCompatibilityTests { } subgraph.removeObserver(observerID) } - #expect(notifiedCount == 0) } - } }