Re: ivar access during -finalize

2012-03-11 Thread Quincey Morris
On Mar 10, 2012, at 23:18 , Eric Wing wrote:

> I don't disagree that finalizers are hard and need to be approached
> with great care. And I agree that all 4 of your points are valid.
> However, I think this description of the retain cycle problem might be
> a little over-dramatic. Retain cycles have always been a problem in
> classic memory management and are still a problem even under ARC. Yet
> there is over a decade's worth of code that managed to write code to
> the Cocoa framework and for the most part avoid retain cycles. With a
> simple scoped problem, well defined strategy, and some care, I think
> this is entirely doable. And if he were to go manual management or
> ARC, he has to avoid retain cycles anyway so he still has to design
> carefully.

I think I'd put it this way:

There's a difference between a retain cycle in a retain/release (RR) app and a 
retain cycle introduced into a GC app by using CFRetain.

In the first case, the app is architected so that cycles are manually broken in 
cases where that's necessary.

In the second case, the app was previously architected to *ignore* any question 
of cycles, since normally they're irrelevant to GC. By using CFRetain, the 
question is no longer irrelevant, and the app may need to be re-architected, 
and the changes may not be local to the places where CFRetain is explicitly 
used. On top of that, in a GC app, you aren't in control of all of the code 
(you're using Cocoa frameworks, other frameworks and libraries, whose internal 
use of references is unknown and unmanageable).

At risk of making another sweeping generalization, I'd say that spending your 
time on doing complicated things with finalization is a terrible waste of 
resources.

The finalization/resource-disposal problem is the *big* drawback to GC apps. 
Retain cycles are the *big* drawback to ARC apps. Both of them require 
considerable design and implementation effort to solve. In Jonathan's case, 
using CGRetain would mean he has to solve *both* at the same time. If he can't 
solve the finalization problem more directly, he'd probably be better off 
re-architecting the app for ARC and just dealing with the cycles**.

But, as I noted before, he could be lucky in using your suggestion. It might be 
two small problems instead of two big problems. :)



** Apart from retain cycle issues, the code for GC and ARC is basically the 
same.


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: Forcing subclass creation through method swizzling not airtight?

2012-03-11 Thread Jean-Daniel Dupas
Yes.
+initialize is not call until you try to use your class.
So there is no garantee it will be call at all, and even if it is called, 
nothing prevent creation of instance of the super class before it append.

Le 11 mars 2012 à 08:05, Antonio Nunes a écrit :

> In the latest public release of my software, I used method swizzling to force 
> creation of my subclass when the system tries to create instances of its 
> superclass. However, I have received a very few reports where apparently 
> instances of the superclass are still created, and wreak havoc (i.e. they 
> cause a crash). In what way is it still possible for instances of the 
> superclass to be created?
> 
> The swizzling is performed early on during the application startup:
> 
> + (void)initialize
> {
>   // To force PDFDocuments to be created as NMD_PDFDocuments
>   // Necessary because of an issue with PDFThumbnailView
>   Method originalMethod = class_getClassMethod([PDFDocument class], 
> @selector(allocWithZone:));
>   Method superMethod = 
> class_getClassMethod(class_getSuperclass([PDFDocument class]), 
> @selector(allocWithZone:));
>   
>   Method replacedMethod = class_getClassMethod([PDFDocument class], 
> @selector(allocWithZoneReplacement:));
>   if (superMethod == originalMethod) {
>   class_addMethod(object_getClass([PDFDocument class]), 
> @selector(allocWithZone:), 
>   
> method_getImplementation(replacedMethod),
>   
> method_getDescription(replacedMethod)->types);
>   }
> 
>   // To force PDFPages to be created as NMD_PDFPage
>   originalMethod = class_getClassMethod([PDFPage class], 
> @selector(allocWithZone:));
>   superMethod = class_getClassMethod(class_getSuperclass([PDFPage 
> class]), @selector(allocWithZone:));
>   
>   replacedMethod = class_getClassMethod([PDFPage class], 
> @selector(allocWithZoneReplacement:));
>   if (superMethod == originalMethod) {
>   class_addMethod(object_getClass([PDFPage class]), 
> @selector(allocWithZone:), 
>   
> method_getImplementation(replacedMethod),
>   
> method_getDescription(replacedMethod)->types);
>   }
> }
> 
> 
> The replacement method lives in a category on PDFPage:
> 
> @implementation PDFPage (PDFPage_AllocWithZoneReplacement)
> 
> // Forces PDFPages to be created as NMD_PDFPages
> + (id)allocWithZoneReplacement:(NSZone *)zone
> {
>   if ([self class] == [PDFPage class]) {
>   return [NMD_PDFPage allocWithZoneReplacement:zone];
>   } else {
>   return [super allocWithZone:zone];
>   }
> }
> 
> @end
> 
> 
> The only change I can think of that might make a difference is to change:
>   if ([self class] == [PDFPage class])
> to
>   if ([self class] != [NMD_PDFPage class])
> 
> but why would this code ever be called for any classes other than either 
> PDFPage or NMD_PDFPage? Maybe someone can point out circumstances under which 
> this whole setup can fail, or be sidestepped.
> 
> -António
> 
> 
> A merry heart does good like medicine
> 
> 
> 
> 
> ___
> 
> Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)
> 
> Please do not post admin requests or moderator comments to the list.
> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
> 
> Help/Unsubscribe/Update your Subscription:
> https://lists.apple.com/mailman/options/cocoa-dev/devlists%40shadowlab.org
> 
> This email sent to devli...@shadowlab.org

-- Jean-Daniel





___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Forcing subclass creation through method swizzling not airtight?

2012-03-11 Thread Antonio Nunes
On 11 Mar 2012, at 09:48, Jean-Daniel Dupas wrote:

> +initialize is not call until you try to use your class.
> So there is no garantee it will be call at all,

Thanks Jean-Daniel,

I think I can be pretty confident it is called, since this initialize is in my 
NSApplication subclass. Should be called before anything is done that involves 
PDF documents and pages.

(By the way, now that I noticed the safeguard was missing, I adjusted the 
method to:

+ (void)initialize
{
if ( self == [NMD_Application class] ) {
...
}
}

> and even if it is called, nothing prevent creation of instance of the super 
> class before it append.

Do you mean before the swizzling occurs? Knowing my code that would be 
unlikely. The only place where I don't control directly what type of page gets 
created is in the PDFThumbnailView when a user drags a PDF document in from the 
Finder, and that can only happen after the app has finished starting up and 
opened a document. But maybe you mean something else by "before it append"?

-António


There is nothing as strong as real gentleness, and
there is nothing as gentle as real strength.






___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: ivar access during -finalize

2012-03-11 Thread jonat...@mugginsoft.com
On 11 Mar 2012, at 08:01, Quincey Morris wrote:

> On Mar 10, 2012, at 23:18 , Eric Wing wrote:
> 
>> I don't disagree that finalizers are hard and need to be approached
>> with great care. And I agree that all 4 of your points are valid.
>> However, I think this description of the retain cycle problem might be
>> a little over-dramatic. Retain cycles have always been a problem in
>> classic memory management and are still a problem even under ARC. Yet
>> there is over a decade's worth of code that managed to write code to
>> the Cocoa framework and for the most part avoid retain cycles. With a
>> simple scoped problem, well defined strategy, and some care, I think
>> this is entirely doable. And if he were to go manual management or
>> ARC, he has to avoid retain cycles anyway so he still has to design
>> carefully.
> 
> I think I'd put it this way:
> 
> There's a difference between a retain cycle in a retain/release (RR) app and 
> a retain cycle introduced into a GC app by using CFRetain.
> 
> In the first case, the app is architected so that cycles are manually broken 
> in cases where that's necessary.
> 
> In the second case, the app was previously architected to *ignore* any 
> question of cycles, since normally they're irrelevant to GC. By using 
> CFRetain, the question is no longer irrelevant, and the app may need to be 
> re-architected, and the changes may not be local to the places where CFRetain 
> is explicitly used. On top of that, in a GC app, you aren't in control of all 
> of the code (you're using Cocoa frameworks, other frameworks and libraries, 
> whose internal use of references is unknown and unmanageable).
> 
> At risk of making another sweeping generalization, I'd say that spending your 
> time on doing complicated things with finalization is a terrible waste of 
> resources.
> 
> The finalization/resource-disposal problem is the *big* drawback to GC apps. 
> Retain cycles are the *big* drawback to ARC apps. Both of them require 
> considerable design and implementation effort to solve. In Jonathan's case, 
> using CGRetain would mean he has to solve *both* at the same time. If he 
> can't solve the finalization problem more directly, he'd probably be better 
> off re-architecting the app for ARC and just dealing with the cycles**.
> 
> But, as I noted before, he could be lucky in using your suggestion. It might 
> be two small problems instead of two big problems. :)


I think both Eric an Quincey are making valid points.

Unrestrained use of CFRetain/CFRelease in a GC app could certainly lead to 
trouble.
It could also be used with restraint, what is probably what Eric had in mind.

The category disposal counting solution that I proposed certainly works.
It has some advantages:
1. Resource disposal isn't tied to the object lifetime so disposal is 
predictable.
2. It doesn't require any code in -finalize.

The downsides are:
1. What is essential (in my case) an internal class resource management problem 
leaks out into the application space as I have to explicity manage the disposal 
count.
2. A failure to balance the disposal retain/release calls will leak data in 
temporary files - which may be a big deal depending on the content.

My conclusion:
1. The CFRetain/CFRelease solution is elegant and will I think suffice for my 
admittedly simple scenario.
2. Under GC CFRetain/CFRelease use the GC ref counting mechanism so we are 
still working with the central GC memory management system.
3. I will be applying the retain/release to ivars which *should* never 
reference self so retain cycles should not be a problem.

I agree with Quincey though that a complicated -finalize method is probably a 
bad -finalize method. 

Regards

Jonathan Mitchell
Mugginsoft LLP



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: Forcing subclass creation through method swizzling not airtight?

2012-03-11 Thread Jean-Daniel Dupas

Le 11 mars 2012 à 13:28, Antonio Nunes a écrit :

> On 11 Mar 2012, at 09:48, Jean-Daniel Dupas wrote:
> 
>> +initialize is not call until you try to use your class.
>> So there is no garantee it will be call at all,
> 
> Thanks Jean-Daniel,
> 
> I think I can be pretty confident it is called, since this initialize is in 
> my NSApplication subclass. Should be called before anything is done that 
> involves PDF documents and pages.
> 
> (By the way, now that I noticed the safeguard was missing, I adjusted the 
> method to:
> 
> + (void)initialize
> {
>   if ( self == [NMD_Application class] ) {
>   ...
>   }
> }
> 
>> and even if it is called, nothing prevent creation of instance of the super 
>> class before it append.
> 
> Do you mean before the swizzling occurs? Knowing my code that would be 
> unlikely. The only place where I don't control directly what type of page 
> gets created is in the PDFThumbnailView when a user drags a PDF document in 
> from the Finder, and that can only happen after the app has finished starting 
> up and opened a document. But maybe you mean something else by "before it 
> append"?
> 

No. If you make sure the class is initialize before anything else append 
(especially before opening any document), and if the safe guard does not fix 
you issue, I don't see why it shouldn't work.

That said, I don't know either how PDFPage instances are created. It is 
perfectly valid for a PDFDocument to explicitly create subclass of PDFPage if 
it want to. In such case, your alloc method will never return a NMD_PDFPage 
instance.

I don't think it has anything to do with you issue, but in your replacement 
method, you can simply use (self == [PDFPage class]) instead of [self class], 
as you are in a class method, and self represent the class itself already.

-- Jean-Daniel





___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Transition from [NSEvent phase] to [NSEvent momentumPhase]

2012-03-11 Thread Markus Spoettl

Hello,

  in a custom view I'm processing -scrollWheel: events for smooth 
scrolling using the trackpad.


When the user flicks across the trackpad, scrolling events first go 
through a phase cycle delivered through [NSEvent phase] 
(NSEventPhaseBegan -> NSEventPhaseChanged -> NSEventPhaseEnded).


After that (depending on how the flick ended physically), the system may 
deliver additional scrolling events with [NSEvent momentumPhase] set 
(NSEventPhaseBegan -> NSEventPhaseChanged -> NSEventPhaseEnded).


A typical sequence of events looks like:

phase: NSEventPhaseBegan / momentumPhase: NSEventPhaseNone
phase: NSEventPhaseChanged / momentumPhase: NSEventPhaseNone
[...]
phase: NSEventPhaseChanged / momentumPhase: NSEventPhaseNone
phase: NSEventPhaseEnded / momentumPhase: NSEventPhaseNone
phase: NSEventPhaseNone / momentumPhase: NSEventPhaseBegan
phase: NSEventPhaseNone / momentumPhase: NSEventPhaseChanged
[...]
phase: NSEventPhaseNone / momentumPhase: NSEventPhaseChanged
phase: NSEventPhaseNone / momentumPhase: NSEventPhaseEnded


The trouble is that there seems no way of knowing that there will be 
momentumPhase events following a "normal" phase cycle. I need to do 
cleanup but I must be sure scrolling is over before doing it.


The system knows (at the time of sending the final normal -phase event) 
that it's going to send additional -momentumPhase events. Is there a way 
to find out?


Regards
Markus
--
__
Markus Spoettl
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com