gnustep-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Multiple _OBJC_Module in the same shared library/framework, not so g


From: Nat!
Subject: Re: Multiple _OBJC_Module in the same shared library/framework, not so good
Date: Tue, 10 Jan 2012 02:08:27 +0100

Am 08.01.2012 um 15:48 schrieb Richard Frith-Macdonald:
Hi Richard

>> 
>> ---
>> A class’s +load method is called after all of its superclasses' +load 
>> methods.
>> A category +load method is called after the class's own +load method.
>> In a +load method, you can therefore safely message other unrelated classes 
>> from the same image, but any +load methods on those classes may not have run 
>> yet.
> 
> Your third point here does not follow from the others  ... unless by 'safely' 
> you are talking about a very specific case:

I'd agree if.., but these are not my words. That's a snippet from the NSObject 
documentation.
(http://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html#//apple_ref/occ/clm/NSObject/load)

> You can call methods in unrelated classes in the same compilation unit, as 
> long as those methods do not (directly or indirectly) call other methods 
> which do not obey the same rule.
> So, yes you can construct code which works to call various methods from 
> +load, but it's so fragile that calling it 'safe' would be perverse.

:)

> 
> In practice that boils down to the rule that you can't safely call any ObjC 
> code from within +load (irrespective of whether you are talking about Apple 
> or GNU) ...

See above documentation snippet, can't agree with you there with respect to 
Apple. I _can_ safely message some other classes there.

I can also not agree with you on GNU, because I can't believe, that self could 
be nil during a GNU +load. If it can't be nil, then logically there exists a 
class, with a subset of your projects objc code callable. What this subset is, 
I will try to deduce form here-on.
 

As David said "+load actually comes with the strongest guarantee, because it 
guarantees not to be run until after all superclasses have been loaded." 


IF +load is called, then it comes with this guarantee. 
BUT +load may also not be called at all...


I tested the following two cases. The first is just a class Y, being dependent 
on X.

libX.so:
        X;
        +[X load]

libY.so:
        Y:X;
        +[Y load]

main:   main.o libX.so  libY.so 

   and

main:   main.o libY.so  libX.so 


Both result in the +load order

        +[X load]
        +[Y load]

And it works, due to quite an effort on the runtime part, because the +load of 
subclass may need to be delayed, for the superclass to appear.


Here is the example, where it fails. Two independent classes A,B and two 
categories on A,B.

libA.so:
        A;
        +[A load]
        +[B(A) load]

libB.so:
        B;
        +[B load]
        +[A(B) load]

main:   main.o libA.so  libB.so

or

main:   main.o libB.so  libA.so


Depending on the link order, either +[B(A) load] or +[A(B) load] is silently 
discarded. Ouch!

(Or are categories then broken as a whole ? I will assume that just +load is 
broken, for the rest of this missive.)


So aside from +load on categories being broken, what else can be said about the 
environment of a class or a category in the current GNU runtime with random 
link order when getting the +load message ?

1) For a class or a category, all superclasses are present, therefore all 
superclasses +load have executed. This allows your code to message your class 
and your superclasses, but you need to be sure, that said message is not 
implemented in a category and that the called message itself isn't calling 
outside the inheritance chain. (If you subclass NSObject, you strictly speaking 
can't message NSString or call a method that calls NSString.) 


2) Q: If the superclass is NOT in the same image, then can it be said, that all 
classes in the image, the superclass resides in, have +loaded ?   

   A: No, because some of them may be delayed for their superclass.

3) Q: If it is known, that this other class residing in the image of my 
superclass has a common superclass with my superclass (f.e. my class subclasses 
either NSResponder or NSScreen in AppKit, which are both subclasses of NSObject 
in Foundation). Is it then known that the other class must also have +loaded ? 

   A: Maybe! 

Imagine two class hierarchies placed into three images

X:Y:Z
  A:Z

lib1.so: X
lib2.so: Y A
lib3.so: Z

--- dlopen lib1.so
X gets delayed (Y)
--- dlopen lib2.so
Y and A get delayed (Z)
--- dlopen lib3.so
Z appears 
+[Z load]
now
+[Y load]
and either
+[X load] +[A load]
or
+[A load] +[X load]

It would be known, that A has loaded before X, if it is guaranteed that delayed 
subclasses (Y A) of a class (Z) are maintained on a FIFO queue on a placeholder 
of that class (Z). (Or some similiar mechanism)

4) Q: If 3) is true, is it then known that categories of A,Y,Z, that reside in 
the dependent images, have +loaded before X ?
   A: No, not without nontrivial additional effort.



> you need to stick to C code in order to avoid someone (perhaps you) coming 
> back to the code later and inadvertently breaking it by modifying one of 
> those other methods your +load calls.
> 
> All is not lost though ... you can almost always get the sort of effect you 
> want by using +load to set variables which are used later in +initialize 
> methods.

Having 3) would be minimal and without 4) I am probably hurting but would be 
OK. Being realistic, I will stick to non-random link order, where all the rules 
change!

Ciao
   Nat!
------------------------------------------------------
Thanks for paying my rent. -- EVH




reply via email to

[Prev in Thread] Current Thread [Next in Thread]