NSDecrementExtraRefCountWasZero

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

NSDecrementExtraRefCountWasZero

David Chisnall-4
Hello the list,

In trying to reduce lock contention for deallocation, I took a bit from the reference count to indicate that weak references exist to an object (and therefore avoid any serialisation on deallocation).  Unfortunately, when Andreas tried testing it, he discovered that this broke NSDecrementExtraRefCountWasZero (and, in theory, NSIncrementExtraRefCount, though not in a way that’s likely to be observable).

On OS X, this function is unavailable in ARC mode and comes with a warning that if any code uses ARC then it may give surprising results.

Looking in GNUstep, it appears that this is called in only a small number of places:

- NSObject is using it, but probably should just be calling objc_retain() / objc_release() / objc_autorelease() (the runtime will call these directly instead of retain / release anyway).  NSProxy, similarly, should simply be calling the relevant functions.

- A few classes are calling it to avoid deallocation of objects that are in a table for reuse.It’s also not clear whether this is still a win: we’ll get more cache contention from refcount manipulations if the objects are small, such as NSIndexPath (though it is required for correctness in a few cases, such as NSConnection).  In these cases, if the runtime supports ARC then we can simply use a strong-to-weak NSHashTable and get rid of most of this logic.

I’d like to start making these changes, and expose some new libobjc2 functions that can provide the functionality of NSDecrementExtraRefCountWasZero (NSIncrementExtraRefCount can be a trivial wrapper around objc_retain().  Currently, the only way I can see of implementing NSDecrementExtraRefCountWasZero on top of the ARC APIs that I can see is to take a weak reference to the object, release it, and then see if the reference is 0.  

It’s also worth noting that both NSDecrementExtraRefCountWasZero and NSIncrementExtraRefCount are currently broken (and will cause memory corruption) if called on blocks (or classes, constant strings, and so on).

David


_______________________________________________
Discuss-gnustep mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/discuss-gnustep
Reply | Threaded
Open this post in threaded view
|

Re: NSDecrementExtraRefCountWasZero

Richard Frith-Macdonald-9


> On 29 Nov 2017, at 12:43, David Chisnall <[hidden email]> wrote:
>
> Hello the list,
>
> In trying to reduce lock contention for deallocation, I took a bit from the reference count to indicate that weak references exist to an object (and therefore avoid any serialisation on deallocation).  Unfortunately, when Andreas tried testing it, he discovered that this broke NSDecrementExtraRefCountWasZero (and, in theory, NSIncrementExtraRefCount, though not in a way that’s likely to be observable).
>
> On OS X, this function is unavailable in ARC mode and comes with a warning that if any code uses ARC then it may give surprising results.
>
> Looking in GNUstep, it appears that this is called in only a small number of places:
>
> - NSObject is using it, but probably should just be calling objc_retain() / objc_release() / objc_autorelease() (the runtime will call these directly instead of retain / release anyway).  NSProxy, similarly, should simply be calling the relevant functions.
>
> - A few classes are calling it to avoid deallocation of objects that are in a table for reuse.It’s also not clear whether this is still a win: we’ll get more cache contention from refcount manipulations if the objects are small, such as NSIndexPath (though it is required for correctness in a few cases, such as NSConnection).  In these cases, if the runtime supports ARC then we can simply use a strong-to-weak NSHashTable and get rid of most of this logic.

That would be good ... at some point it would be great if the core libraries could make use of ARC.

> I’d like to start making these changes, and expose some new libobjc2 functions that can provide the functionality of NSDecrementExtraRefCountWasZero (NSIncrementExtraRefCount can be a trivial wrapper around objc_retain().  Currently, the only way I can see of implementing NSDecrementExtraRefCountWasZero on top of the ARC APIs that I can see is to take a weak reference to the object, release it, and then see if the reference is 0.  

Presumably the downside of that is fairly severe inefficiency, but since thew functions are rarely used that's probably not a big issue; if it turns out a class using the reference count functions has a major performance impace when used with ARC, I guess that class could be rerwritten.

> It’s also worth noting that both NSDecrementExtraRefCountWasZero and NSIncrementExtraRefCount are currently broken (and will cause memory corruption) if called on blocks (or classes, constant strings, and so on).

I don't think that's a practical issue since it's always been clear that those functions are provided for classes to manage their own reference counting.   I wouldn't worry about trying to make them work for any/all args.


_______________________________________________
Discuss-gnustep mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/discuss-gnustep
Reply | Threaded
Open this post in threaded view
|

Re: NSDecrementExtraRefCountWasZero

David Chisnall
On 30 Nov 2017, at 08:52, Richard Frith-Macdonald <[hidden email]> wrote:

>
>
>
>> On 29 Nov 2017, at 12:43, David Chisnall <[hidden email]> wrote:
>>
>> Hello the list,
>>
>> In trying to reduce lock contention for deallocation, I took a bit from the reference count to indicate that weak references exist to an object (and therefore avoid any serialisation on deallocation).  Unfortunately, when Andreas tried testing it, he discovered that this broke NSDecrementExtraRefCountWasZero (and, in theory, NSIncrementExtraRefCount, though not in a way that’s likely to be observable).
>>
>> On OS X, this function is unavailable in ARC mode and comes with a warning that if any code uses ARC then it may give surprising results.
>>
>> Looking in GNUstep, it appears that this is called in only a small number of places:
>>
>> - NSObject is using it, but probably should just be calling objc_retain() / objc_release() / objc_autorelease() (the runtime will call these directly instead of retain / release anyway).  NSProxy, similarly, should simply be calling the relevant functions.
>>
>> - A few classes are calling it to avoid deallocation of objects that are in a table for reuse.It’s also not clear whether this is still a win: we’ll get more cache contention from refcount manipulations if the objects are small, such as NSIndexPath (though it is required for correctness in a few cases, such as NSConnection).  In these cases, if the runtime supports ARC then we can simply use a strong-to-weak NSHashTable and get rid of most of this logic.
>
> That would be good ... at some point it would be great if the core libraries could make use of ARC.

This should be fairly easy now, but only if we’re willing to drop support for GCC - it’s very difficult to maintain code that can compile as both ARC and non-ARC.

>
>> I’d like to start making these changes, and expose some new libobjc2 functions that can provide the functionality of NSDecrementExtraRefCountWasZero (NSIncrementExtraRefCount can be a trivial wrapper around objc_retain().  Currently, the only way I can see of implementing NSDecrementExtraRefCountWasZero on top of the ARC APIs that I can see is to take a weak reference to the object, release it, and then see if the reference is 0.  
>
> Presumably the downside of that is fairly severe inefficiency, but since thew functions are rarely used that's probably not a big issue; if it turns out a class using the reference count functions has a major performance impace when used with ARC, I guess that class could be rerwritten.

Thinking a bit more, it’s actually not a good solution, because that will deallocate the object, so I will need to add a new runtime hook.  This will probably involve some juggling with weak functions.

>> It’s also worth noting that both NSDecrementExtraRefCountWasZero and NSIncrementExtraRefCount are currently broken (and will cause memory corruption) if called on blocks (or classes, constant strings, and so on).
>
> I don't think that's a practical issue since it's always been clear that those functions are provided for classes to manage their own reference counting.   I wouldn't worry about trying to make them work for any/all args.

I’ve been going through the uses in -base and converting them to use weak references. I’ve come across what looks like a bug in NSSocketPort.m.  We create an NSMapTable with NSObjectMapKeyCallBacks and NSNonOwnedPointerMapValueCallBacks.  We then use portNum (a uint16_t) as the key.  I don’t understand how this doesn’t crash at run time (that said, I don’t know if I’ve ever used anything that uses NSSocketPort).

David


_______________________________________________
Discuss-gnustep mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/discuss-gnustep
Reply | Threaded
Open this post in threaded view
|

Re: NSDecrementExtraRefCountWasZero

Andreas Fink-2


> On 3 Dec 2017, at 11:46, David Chisnall <[hidden email]> wrote:
>
> On 30 Nov 2017, at 08:52, Richard Frith-Macdonald <[hidden email]> wrote:
>>
>>
>>
>>> On 29 Nov 2017, at 12:43, David Chisnall <[hidden email]> wrote:
>>>
>>> Hello the list,
>>>
>>> In trying to reduce lock contention for deallocation, I took a bit from the reference count to indicate that weak references exist to an object (and therefore avoid any serialisation on deallocation).  Unfortunately, when Andreas tried testing it, he discovered that this broke NSDecrementExtraRefCountWasZero (and, in theory, NSIncrementExtraRefCount, though not in a way that’s likely to be observable).
>>>
>>> On OS X, this function is unavailable in ARC mode and comes with a warning that if any code uses ARC then it may give surprising results.
>>>
>>> Looking in GNUstep, it appears that this is called in only a small number of places:
>>>
>>> - NSObject is using it, but probably should just be calling objc_retain() / objc_release() / objc_autorelease() (the runtime will call these directly instead of retain / release anyway).  NSProxy, similarly, should simply be calling the relevant functions.
>>>
>>> - A few classes are calling it to avoid deallocation of objects that are in a table for reuse.It’s also not clear whether this is still a win: we’ll get more cache contention from refcount manipulations if the objects are small, such as NSIndexPath (though it is required for correctness in a few cases, such as NSConnection).  In these cases, if the runtime supports ARC then we can simply use a strong-to-weak NSHashTable and get rid of most of this logic.
>>
>> That would be good ... at some point it would be great if the core libraries could make use of ARC.
>
> This should be fairly easy now, but only if we’re willing to drop support for GCC - it’s very difficult to maintain code that can compile as both ARC and non-ARC.


Which raises the question on how many people use Objective C and still use GCC?
If you use ObjectiveC 2.0 features such as automatic properties or ARC, you for sure will use clang. GCC is a real deal breaker there.
In my project, ARC made a lot of stuff a lot simpler to code and avoided a lot of human errors. ARC saves your there.

I'm not sure who else uses GNUStep-base in what scenario and if supporting GCC is still kind of a important thing to keep around or not.



_______________________________________________
Discuss-gnustep mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/discuss-gnustep
Reply | Threaded
Open this post in threaded view
|

Re: NSDecrementExtraRefCountWasZero

David Chisnall
On 3 Dec 2017, at 10:01, Andreas Fink <[hidden email]> wrote:
>
> Which raises the question on how many people use Objective C and still use GCC?

I haven’t for a long time, but last time we discussed it some people were very vocal about keeping GCC support.  

> If you use ObjectiveC 2.0 features such as automatic properties or ARC, you for sure will use clang. GCC is a real deal breaker there.

GCC does support declared properties, but it doesn’t support ARC.  I’ve spoken to someone who is interested in adding ARC support to GCC a couple of times, but he’s always been too busy with other projects to get around to it (they had a customer who wanted blocks in GCC, so he was working on that and became interested in ARC).  ARC is a very complex feature to get right (there are complex rules about how scopes relate to lifetimes, which are part of the reason why ARC saves a lot of code)

> In my project, ARC made a lot of stuff a lot simpler to code and avoided a lot of human errors. ARC saves your there.
>
> I'm not sure who else uses GNUStep-base in what scenario and if supporting GCC is still kind of a important thing to keep around or not.

I think being able to use ARC in -gui and -base would save us a lot of effort, but the biggest gain would be being able to delete a load of compatibility code.

That said, I’d be far more inclined to suggest that we depend on Objective-C++ and libobjc2 than clang.  GSIMap, for example, is quite painful to use and would be a lot cleaner in C++.  In other code bases, I can simply do things like std::unordered_map<int, id __weak> and all of the memory management works correctly.  Before we had reliable ARC support, I had some C++ strong_object and weak_object wrappers that called the relevant runtime functions in their constructors and destructors (and, for weak, implemented an implicit cast operator to a strong object type that called the function to materialise a strong reference).

David


_______________________________________________
Discuss-gnustep mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/discuss-gnustep
Reply | Threaded
Open this post in threaded view
|

Re: NSDecrementExtraRefCountWasZero

Ivan Vučica-2

ned, 3. pro 2017. u 11:17 David Chisnall <[hidden email]> napisao je:

That said, I’d be far more inclined to suggest that we depend on Objective-C++ and libobjc2 than clang.  GSIMap, for example, is quite painful to use and would be a lot cleaner in C++.  In other code bases, I can simply do things like std::unordered_map<int, id __weak> and all of the memory management works correctly.  Before we had reliable ARC support, I had some C++ strong_object and weak_object wrappers that called the relevant runtime functions in their constructors and destructors (and, for weak, implemented an implicit cast operator to a strong object type that called the function to materialise a strong reference).

I am not a fan of C++. I’d be okay with this only if it meant no regressions in output code size and, more importantly, compile times.
--
Sent from Gmail Mobile on iPad

_______________________________________________
Discuss-gnustep mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/discuss-gnustep