Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial port of WinObjC's KVO implementation to GNUstep #420

Merged
merged 47 commits into from
Nov 10, 2024
Merged

Conversation

hmelder
Copy link
Contributor

@hmelder hmelder commented Jun 11, 2024

Summary:
This pull request introduces an initial port of the Key-Value Observing (KVO) implementation from Microsoft's WinObjC to GNUstep. The existing implementation in GNUstep has various issues (See #324).

Details:

  • The KVO implementation has been ported from ObjC++ to ObjC.
  • This port is specifically available for Clang with libobjc2.
  • The existing KVO implementation is now marked as legacy and is maintained for the GCC toolchain.
  • Test cases have been ported to Objective-C and integrated with the GNUstep test framework.

References:

@hmelder hmelder requested a review from rfm as a code owner June 11, 2024 16:34
@triplef
Copy link
Member

triplef commented Jun 12, 2024

These changes are based on the patch we’ve been using in our app (see #324) and also contain additional fixes on top of the WinObjC implementation.

Copy link
Contributor

@rfm rfm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would really have liked to upgrade the existing implementation with the few missing features rather than depending on objc2, but having looked at the code the dependency on the runtime library and the degree of optimisation (particularly the fine control of ARC) I can see why that would be difficult.

I'm not sure that the reworking of GSAtomic.h is necessary, but renaming functions with a gs_ prefix seems like a good thing even if it's not needed.

I think the C++ change in GSPThread.h should be removed though, since we aren't using C++ internally.

The rest looks reasonable, once we accept that we are tolerating the internal use of objc2 features (and minor coding style issues), though I can't say I'm familiar with the runtime library internals that the class swizzling depends upon.

@triplef
Copy link
Member

triplef commented Jun 12, 2024

I think adding the prefix for our atomic macros had been necessary to avoid name clashes with the stdatomic.h header.

All the extern "C" code should indeed be removed since none of the code is C++ (any more).

Maybe it would be a good idea to start a list with features that require libobjc2 e.g. in the readme (I think NSURLSession and this so far)?

NSObject (NSKeyValueObserving)
/**
@Status Interoperable
*/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can probably remove all these @Status Interoperable comments from WinObjC.

@rfm
Copy link
Contributor

rfm commented Jun 12, 2024 via email

@hmelder
Copy link
Contributor Author

hmelder commented Jun 12, 2024

We really aren't supposed to have features that don't work with one compiler/runtime as logn as we are supporting both.

If one toolchain does not offer or restricts the capabilities needed, it should not slow down overall progress. Associated Objects (which are used in this KVO implementation) are an example for this.

@rfm
Copy link
Contributor

rfm commented Jun 12, 2024 via email

@rfm
Copy link
Contributor

rfm commented Jun 12, 2024

Or of course, as in this case, we can have two KVO implementations ... OK, but not as good from a maintainability point of view as a single implementation.

@hmelder
Copy link
Contributor Author

hmelder commented Jun 12, 2024

Ganerally I'd advocate adding general purpose compatibility features where sutiable features are available, rather than designing new ones.

I understand your point, but even for NSURLSession, this would mean using the libdispatch APIs with C functions, adding autorelease pools to each C function, and using methods instead of blocks for delegate dispatching.

Quite a pain and increase in complexity...
I'd be willing to review the changes tho :)

Source/NSUserDefaults.m Outdated Show resolved Hide resolved
@hmelder
Copy link
Contributor Author

hmelder commented Jun 22, 2024

I need to test the changes made to the legacy KVO implementation.

@hmelder
Copy link
Contributor Author

hmelder commented Jun 26, 2024

The Signature Cache in NSMethodSignature results in up to 36% speed-up of KVO willChange/didChange dispatching.

@rfm can you review the changes to NSMethodSignature, NSKeyValueObserving, and other existing classes?

image

@hmelder
Copy link
Contributor Author

hmelder commented Jun 26, 2024

We can shave of another 100-150ms if we reuse change dictionaries. KVO on NSSet's is also really inefficient atm because of a copy operation inside willChange[...] and computation of the changes.

@rfm
Copy link
Contributor

rfm commented Jun 26, 2024

I actually looked at the signature cache code yesterday, and was thinking I should suggest that you commit that separately since it's not actually linked to the KVO code in any way, and it seemed a very clearly good idea!

@rfm
Copy link
Contributor

rfm commented Jun 26, 2024

We can shave of another 100-150ms if we reuse change dictionaries.
This we need to check carefully (more than I've had chance to). Re-use makes sense but last version I looked at, I thought the change dictionaries were mutable, and re-use would be bad if user code can alter the dictionary. From my cursory review I wasn't sure it would be safe.

@triplef
Copy link
Member

triplef commented Jun 26, 2024

Yes good point @rfm, plus we need to ensure multi-thread support is maintained (see also my comment on the static NSNumber above).

@hmelder
Copy link
Contributor Author

hmelder commented Jun 26, 2024

we need to ensure multi-thread support is maintained

It is probably worth then to write a few test cases...

@hmelder
Copy link
Contributor Author

hmelder commented Jun 26, 2024

(see also my comment on the static NSNumber above).

I cannot see it on GH :(

@triplef triplef force-pushed the kvo_winobjc branch 3 times, most recently from 1eebad8 to dbe8f19 Compare June 27, 2024 10:06
@fredkiefer
Copy link
Member

Could we try to get the tests working with the old ObjC runtime as well? Of course we need to flag some tests as hopeful there. But that way we better see the missing functionality.
i am willing to help with the rewrite if we can agree on it.

@hmelder
Copy link
Contributor Author

hmelder commented Jul 2, 2024

Could we try to get the tests working with the old ObjC runtime as well?

Sure!

@triplef triplef force-pushed the kvo_winobjc branch 2 times, most recently from b0743eb to 64b4f0e Compare August 12, 2024 07:46
@triplef
Copy link
Member

triplef commented Aug 12, 2024

I rebased onto master to fix some merge conflicts.

@hmelder
Copy link
Contributor Author

hmelder commented Aug 12, 2024

@rfm what's the status of this PR? Can we merge it, or are there still some tests that need to be refactored for older versions of ObjC?

@rfm
Copy link
Contributor

rfm commented Aug 12, 2024

You were going to address Fred's request for portable testcases. I have done partial fixes recently but afaik there's still quite a bit of broken (ie dependent on Apple/clang specific features) code there.

@hmelder
Copy link
Contributor Author

hmelder commented Oct 14, 2024

doesn't work. Just swich commenting out the two methods here: https://github.com/buzzdeee/TestObserver/blob/main/DSASpell.m

Fixed in bf40916

@buzzdeee
Copy link
Contributor

doesn't work. Just swich commenting out the two methods here: https://github.com/buzzdeee/TestObserver/blob/main/DSASpell.m

Fixed in bf40916

Just tested this last patch version, in my main app, where I have the keyPathsForValuesAffectingValueForKey: method already prepared, suddenly started to work with that. Awesome!

@triplef
Copy link
Member

triplef commented Oct 15, 2024

We’ve also tested this patch with our apps and found no issues.

@hmelder
Copy link
Contributor Author

hmelder commented Oct 15, 2024

Seems like the NSURLSession tests fail sometimes because of swiftlang/swift-corelibs-libdispatch#833

This is unrelated.

Source/NSKVOInternal.h Outdated Show resolved Hide resolved
Source/NSUserDefaults.m Outdated Show resolved Hide resolved
Copy link
Contributor

@rfm rfm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry it's taken be so long to get round to this, but I think this is well tested and clean enough to merge now.

@hmelder hmelder merged commit 6681a3d into master Nov 10, 2024
8 checks passed
@hmelder hmelder deleted the kvo_winobjc branch November 10, 2024 16:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

5 participants