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" } }, { 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/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/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/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/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/*, ...*/); 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/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/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/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/Graph/SubgraphCompatibilityTests.swift b/Tests/OpenAttributeGraphCompatibilityTests/Graph/SubgraphCompatibilityTests.swift index 20b44e60..b08dd697 100644 --- a/Tests/OpenAttributeGraphCompatibilityTests/Graph/SubgraphCompatibilityTests.swift +++ b/Tests/OpenAttributeGraphCompatibilityTests/Graph/SubgraphCompatibilityTests.swift @@ -28,4 +28,52 @@ struct SubgraphCompatibilityTests { Subgraph.endTreeElement(value: value) } } + + @Suite + struct ObserverTests { + @Test + func observerNotifiedOnSubgraphDestroyed() { + var notifiedCount = 0 + do { + let graph = Graph() + do { + 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 + 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 + do { + let graph = Graph() + let subgraph = Subgraph(graph: graph) + let observerID = subgraph.addObserver { + notifiedCount += 1 + } + subgraph.removeObserver(observerID) + } + #expect(notifiedCount == 0) + } + } } 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