Re: storage for context: value

2013-07-25 Thread Quincey Morris
On Jul 25, 2013, at 12:08 , Matt Neuburg  wrote:

> Well, and discussions of the issue often fail to take into account the 
> problem of distinguishing the context on an instance-by-instance basis. 
> Passing "self" as a context does that, obviously; but the "static void*" 
> trick does not (there is one storage per class, not per instance of that 
> class).

In the 'observeValueForKeyPath' scenario (keeping in mind that it's a broken 
API design), using 'self' is dangerous because it's not unique enough. A 
superclass-defined observation may cleverly try to use it too.

> If an informative data structure is to be used on an instance-by-instance 
> basis, and if this data structure is to persist, then it seems to me that it 
> *must* be an instance variable.


When you say "instance variable" I think there are actually 3 different 
possibilities:

1. You want a per-instance value, which is stored in an ivar specifically for 
that purpose.

2. You might get away with using the address of an ivar that's private to your 
class (whose value is something unrelated). The address is unique to the 
instance and class, because superclasses and subclasses won't be using it.

3. You might still need a per-observation-per-instance context tag, in which 
case #1 and #2 don't work. This is particularly relevant to the new form of 
'removeObserver'.

If it were me, I would use a per-class tag (such as the static variable 
address) when I could, or a per-observation UID otherwise. Using a per-instance 
UID -- anything unique only to the level of 'self' -- seems too dangerous these 
days. The likelihood of the class having -- or later  adding -- multiple 
observations on the same thing seems too high.

___

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: storage for context: value

2013-07-25 Thread Matt Neuburg
Well, and discussions of the issue often fail to take into account the problem 
of distinguishing the context on an instance-by-instance basis. Passing "self" 
as a context does that, obviously; but the "static void*" trick does not (there 
is one storage per class, not per instance of that class). If an informative 
data structure is to be used on an instance-by-instance basis, and if this data 
structure is to persist, then it seems to me that it *must* be an instance 
variable. m.

On Jul 25, 2013, at 9:19 AM, Quincey Morris 
 wrote:

> On Jul 25, 2013, at 07:20 , Matt Neuburg  wrote:
> 
>> storage of the value passed as context:(void*), not just in addObserver:, 
>> but in general
> 
> I think I'd take this in a different direction. In *all* of these scenarios 
> the context parameter is a mechanism for passing a pointer to a data 
> structure to a callback/completion routine/handler with a generic signature, 
> as Roland already said.
> 
> That leads to a set of potential pitfalls:
> 
> -- Memory management. If the data structure is allocated memory (C idiom) or 
> an object (ObjC idiom), it's not trivial to manage its lifetime.
> 
> -- Heterogeneity. If contexts of different idioms are fed to the same 
> handler, it can be difficult to decide what data structure is being pointed 
> to.
> 
> -- Complexity. If the data structure pointed to is just a single value (such 
> as a simple type, or a simple identifier), it can take a lot of code to 
> package this in a real data structure that behaves properly wrt the first 2 
> pitfalls.
> 
> The 'static void* x = &x;' convention you mention (a "pointer as tag" 
> convention) is significant only because it's a very elegant way to avoid all 
> 3 pitfalls, when no additional data needs to be passed. It also has the 
> virtue of relieving the developer from the need to remember whether to put a 
> '&' on the front of the argument.
> 
> The story behind 'addObserver' (or, really, the story behind 
> 'observeValueForKeyPath') is a separate matter. This particular API was 
> misdesigned, because it did not properly envisage a need to identify multiple 
> observations of the same thing. Thus, the 'context' parameter came to be used 
> as this identification -- there was no actual data structure to be passed in. 
> The above "pointer as tag" convention bubbled to the top of the pile as the 
> most convenient way to solve the problem.
> 

--
matt neuburg, phd = m...@tidbits.com, http://www.apeth.net/matt/
pantes anthropoi tou eidenai oregontai phusei
Programming iOS 6! http://shop.oreilly.com/product/0636920029717.do
RubyFrontier! http://www.apeth.com/RubyFrontierDocs/default.html
TidBITS, Mac news and reviews since 1990, http://www.tidbits.com


___

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: storage for context: value

2013-07-25 Thread Quincey Morris
On Jul 25, 2013, at 07:20 , Matt Neuburg  wrote:

> storage of the value passed as context:(void*), not just in addObserver:, but 
> in general

I think I'd take this in a different direction. In *all* of these scenarios the 
context parameter is a mechanism for passing a pointer to a data structure to a 
callback/completion routine/handler with a generic signature, as Roland already 
said.

That leads to a set of potential pitfalls:

-- Memory management. If the data structure is allocated memory (C idiom) or an 
object (ObjC idiom), it's not trivial to manage its lifetime.

-- Heterogeneity. If contexts of different idioms are fed to the same handler, 
it can be difficult to decide what data structure is being pointed to.

-- Complexity. If the data structure pointed to is just a single value (such as 
a simple type, or a simple identifier), it can take a lot of code to package 
this in a real data structure that behaves properly wrt the first 2 pitfalls.

The 'static void* x = &x;' convention you mention (a "pointer as tag" 
convention) is significant only because it's a very elegant way to avoid all 3 
pitfalls, when no additional data needs to be passed. It also has the virtue of 
relieving the developer from the need to remember whether to put a '&' on the 
front of the argument.

The story behind 'addObserver' (or, really, the story behind 
'observeValueForKeyPath') is a separate matter. This particular API was 
misdesigned, because it did not properly envisage a need to identify multiple 
observations of the same thing. Thus, the 'context' parameter came to be used 
as this identification -- there was no actual data structure to be passed in. 
The above "pointer as tag" convention bubbled to the top of the pile as the 
most convenient way to solve the problem.

___

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: storage for context: value

2013-07-25 Thread Scott Ribe
On Jul 25, 2013, at 8:50 AM, Matt Neuburg  wrote:

> But surely that can't work, since you set up the call once but you can get 
> called back many times - or am I misunderstanding? m.

Sorry, that depends on the callback, and I was thinking specifically of 
one-shot ones. (Think of beginSheetModalForWindow…)

Where the callback has an indefinite lifetime, then yes, the release must be 
handled somewhere else. But the basic point still applies, if you release the 
context info only at the point where you deactivate the callback, you're 
good--and yes I've done that too.

Of course another way is to have an object that owns both the callback and 
related info, that instantiates the callback and passes itself as the context 
info, and deactivates the callback and releases the related info at the same 
time.

Regardless, you need simple & clear & consistent single points of construction 
& destruction of the information.

-- 
Scott Ribe
scott_r...@elevated-dev.com
http://www.elevated-dev.com/
(303) 722-0567 voice





___

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: storage for context: value

2013-07-25 Thread Roland King
Well the second two examples of those are rather different from the first. 

In the case of sortedArrayUsingFunction:context: and beginAnimations:context: 
the context is there really as an opaque pointer to pass data into the 
function. That pattern of function +  was the pre-blocks way to pass contextual information into a generic 
function, eg say you wanted to sort descending or with some options, that would 
go in your context in a function-dependent way. Same with 
beingAnimations:context: (although is anyone using that method any more? That 
was 'discouraged' after iOS4 and if you aren't using the block-based animations 
by now .. it's time) again this gave you a way to pass per-animation 
information in that you wanted to retrieve later. 

So in those cases the context would usually be a shorter-lived thing used 
really for the life of the call only and then discarded, often an object cast 
to void*. 

the NSKVO context. Technically I suppose you could use that in the same way, if 
you had an instance of an object which set up more than one observation on the 
same property of the same other object for more than one reason (I can't think 
of one offhand but it could happen) you could use the context pointer to 
disambiguate them and do something different in your observe... method, because 
you only get one observe method. Most of the time however the context in that 
exists not to disambiguate between multiple observations of the same property 
of one object registered by you, but to deal with subclasses observing the same 
exact property as their superclass on the same object. There will be two 
observations sent to the instance, each one needs to handle just one of them. 

In that normal case there you don't care about any actual context of where you 
set the observation up, you probably don't even care about which instance of 
your class set it up, you normally just care that this is an observation to be 
handled in the observe.. method implementation in that particular class, so the 
generic thing to use is anything at class scope, one of the easiest ways to do 
that is the static void *X = &X which gives you something only that class has, 
is already a void*. I've also used the [ xxx class ] properly cast and I think 
I've used the actual class instance too, probably out of idiocy. 



On 25 Jul, 2013, at 10:20 PM, Matt Neuburg  wrote:

> I'd like to hear some arguments / opinions / essays on storage of the value 
> passed as context:(void*), not just in addObserver:, but in general - so, 
> including things like beginAnimations:context: and 
> sortedArrayUsingFunction:context:.
> 
> Must it always be an external variable? Must it always be stored as a void*? 
> I know there's a standard pattern where it's an external pointing to its own 
> storage:
> 
>static void* const MYCONTEXT = (void*)&MYCONTEXT;
> 
> Is this the only safe/sensible storage? Could it be an actual object, cast 
> back and forth between id and void*? Could it be stored as an ivar? Thx as 
> always - m.
> 
> --
> matt neuburg, phd = m...@tidbits.com, http://www.apeth.net/matt/
> pantes anthropoi tou eidenai oregontai phusei
> Programming iOS 6! http://shop.oreilly.com/product/0636920029717.do
> RubyFrontier! http://www.apeth.com/RubyFrontierDocs/default.html
> TidBITS, Mac news and reviews since 1990, http://www.tidbits.com
> 
> 
> ___
> 
> 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/rols%40rols.org
> 
> This email sent to r...@rols.org

___

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: storage for context: value

2013-07-25 Thread Matt Neuburg

On Jul 25, 2013, at 7:33 AM, Scott Ribe  wrote:

> If you alloc an object per callback setup, right where you set up the 
> callback, and release it in the callback, you're safe--and that's a very 
> common pattern I think

But surely that can't work, since you set up the call once but you can get 
called back many times - or am I misunderstanding? m.

--
matt neuburg, phd = m...@tidbits.com, http://www.apeth.net/matt/
pantes anthropoi tou eidenai oregontai phusei
Programming iOS 6! http://shop.oreilly.com/product/0636920029717.do
RubyFrontier! http://www.apeth.com/RubyFrontierDocs/default.html
TidBITS, Mac news and reviews since 1990, http://www.tidbits.com


___

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: storage for context: value

2013-07-25 Thread Scott Ribe
On Jul 25, 2013, at 8:20 AM, Matt Neuburg  wrote:

> Is this the only safe/sensible storage? Could it be an actual object, cast 
> back and forth between id and void*? Could it be stored as an ivar? Thx as 
> always - m.

No, of course, and yes ;-)

Now the static idiom you mentioned is nice in that you don't have to worry 
about it going out of scope just because a function completes and the stack 
frame is destroyed, and because at least the variable itself does not get 
munged. But of course to be useful, MYCONTEXT might have to hold references to 
objects, and then you're back to having to manage the lifetimes of what is 
referred to. Also, it's only good when you only need 1 of the particular 
callback/info combinations to be active, and I find that's an unrealistic 
restriction, and is why I have (IIRC) never used this idiom. Note: I'm 
developing Mac software, so most of my windows/controllers can (and in normal 
use often will) have multiple instances existing at once. (In iOS I expect that 
it would be far more common to have window/controller pairs where there is 
never more than instance in simultaneous existence.)

I think the issue of *what* the context info refers to is far far less 
important than the issue of controlling the contexts (harhar) in which it is 
managed. If you're retaining/releasing them all throughout your code, you're 
asking for trouble. If you alloc an object per callback setup, right where you 
set up the callback, and release it in the callback, you're safe--and that's a 
very common pattern I think.

-- 
Scott Ribe
scott_r...@elevated-dev.com
http://www.elevated-dev.com/
(303) 722-0567 voice





___

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