Closed Bug 307713 Opened 19 years ago Closed 19 years ago

Improve and use nsAgg's macros

Categories

(Core :: XPCOM, defect, P4)

defect

Tracking

()

RESOLVED FIXED
mozilla1.9alpha1

People

(Reporter: peterv, Assigned: peterv)

References

Details

Attachments

(1 file, 1 obsolete file)

I think we should make NS_IMPL_AGGREGATED_QUERY_HEAD return the inner for the
nsISupports IID and add macros to define a constructor. Doing that would cut
down on possible errors when implementing an aggregated class. I've converted
many of the classes in the tree that already use nsAgg to use these proposed
macros. Patch coming up.
Attached patch v1 (obsolete) — Splinter Review
Attachment #195413 - Flags: superreview?(darin)
Attachment #195413 - Flags: review?(dougt)
Blocks: 278981
Comment on attachment 195413 [details] [diff] [review]
v1

Did you consider making the  NS_GENERIC_AGGREGATED_CONSTRUCTOR/_INIT macros
mirror the macros in nsIGenericFactory.h?  Those macros are designed to be used
in the module implementation file, which avoids the need to forward declare
them in class header files, and moreover makes it possible for them to be
defined file static.  Unless there is compelling reason not to, I would try to
mimic those here.
(In reply to comment #2)
> (From update of attachment 195413 [details] [diff] [review] [edit])
> Did you consider making the  NS_GENERIC_AGGREGATED_CONSTRUCTOR/_INIT macros
> mirror the macros in nsIGenericFactory.h?  Those macros are designed to be used
> in the module implementation file, which avoids the need to forward declare
> them in class header files, and moreover makes it possible for them to be
> defined file static.  Unless there is compelling reason not to, I would try to
> mimic those here.

That would mean either making the constructor function a friend of the class
(which doesn't give us much over forward declaring) or making Inner() public
because the constructor needs to QI, AddRef and Release the inner. Let me know
if you prefer that.
> That would mean either making the constructor function a friend of the class
> (which doesn't give us much over forward declaring) or making Inner() public
> because the constructor needs to QI, AddRef and Release the inner. Let me know
> if you prefer that.

Ah, I see.  Without your patch those constructor methods are calling
AggregatedQueryInterface directly, but with your patch, they are calling through
Inner()->QueryInterface.  Can you explain why you made that change?  It would
seem to me that if you made the constructors call AggregatedQueryInterface, then
you would 1) have a slightly shorter code path and 2) allow the constructors to
be non-friend, static functions.
(In reply to comment #4)
> It would
> seem to me that if you made the constructors call AggregatedQueryInterface, then
> you would 1) have a slightly shorter code path and 2) allow the constructors to
> be non-friend, static functions.

Sure, I can call AggregatedQueryInterface but I still wouldn't be able to call
AddRef and Release on the inner when there's an init method to be called. So
we'd need to make the AddRef/Release public then.
-NS_METHOD
-nsJVMAuthTools::Create(nsISupports* outer,
-                       const nsIID& aIID,
-                       void* *aInstancePtr)
-{
-    if (!aInstancePtr)
-        return NS_ERROR_INVALID_POINTER;
-    *aInstancePtr = nsnull;
-
-    if (outer && !aIID.Equals(kISupportsIID))
-        return NS_ERROR_INVALID_ARG; 
-
-    nsJVMAuthTools* authtools = new nsJVMAuthTools(outer);
-    if (authtools == nsnull)
-        return NS_ERROR_OUT_OF_MEMORY;
-
-    nsresult rv = authtools->AggregatedQueryInterface(aIID, aInstancePtr);
-    if(NS_FAILED(rv))
-        delete authtools;
-
-    return rv;
-}

What AddRef and Release?  Was this old code broken in some way?
BTW, having Init be public is nothing new.  That is already par for the course
for the constructors provided by nsIGenericFactory.h.
Note for example nsProperties::Create, which currently has an error: it calls
AddRef/Release on the nsProperties instance which will forward to the outer. You
want to keep the nsProperties instance alive while you Init it, not the outer.
Yup, good point.  OK, well... so much for consistency with nsIGenericFactory.h! ;)
Well, I'm sorta sad myself that they're alike but not identical. I wonder if we
should just make Inner() public. Nobody's supposed to call it, but nobody's
supposed to call AggregatedQueryInterface() directly either :-)
Comment on attachment 195413 [details] [diff] [review]
v1

>Index: modules/oji/src/scd.cpp

>+    if (outer && !aIID.Equals(NS_GET_IID(nsISupports)))
>         return NS_ERROR_INVALID_ARG;

use NS_ENSURE_PROPER_AGGREGATION ?


>Index: netwerk/base/src/nsSimpleURI.cpp

>@@ -78,7 +78,7 @@ nsSimpleURI::AggregatedQueryInterface(co
>     NS_ENSURE_ARG_POINTER(aInstancePtr);
> 
>     if (aIID.Equals(kISupportsIID)) {
>-        *aInstancePtr = GetInner();
>+        *aInstancePtr = Inner();
>     } else if (aIID.Equals(kThisSimpleURIImplementationCID) || // used by Equals
>                aIID.Equals(NS_GET_IID(nsIURI))) {
>         *aInstancePtr = NS_STATIC_CAST(nsIURI*, this);

You could probably make this use the new macro by defining 
kThisSimpleURIImplementationCID as an "IID" on nsSimpleURI.
Then you could just add this to the interface map:

  NS_INTERFACE_MAP_ENTRY(nsSimpleURI)


sr=darin
Attachment #195413 - Flags: superreview?(darin) → superreview+
hmm... if you make Inner() public, then perhaps AggregatedQueryInterface would
not need to be public?  Also, does AggregatedQueryInterface really need to be
virtual?
Attached patch v1.1Splinter Review
Made Inner() public and the rest private. The macros mimic the generic factory
ones.

> >	} else if (aIID.Equals(kThisSimpleURIImplementationCID) || // used by
Equals
> >		   aIID.Equals(NS_GET_IID(nsIURI))) {
> >	    *aInstancePtr = NS_STATIC_CAST(nsIURI*, this);
> 
> You could probably make this use the new macro by defining 
> kThisSimpleURIImplementationCID as an "IID" on nsSimpleURI.
> Then you could just add this to the interface map:
> 
>   NS_INTERFACE_MAP_ENTRY(nsSimpleURI)

Unfortunately, that doesn't work because nsISupports is an ambiguous base class
of nsSimpleURI. The macros expect the class that has the static IID accessor to
be unambiguously derived from nsISupports.

Darin, I carried your sr over to this one but feel free to review it once more.
Attachment #195413 - Attachment is obsolete: true
Attachment #196022 - Flags: superreview+
Attachment #196022 - Flags: review?(dougt)
Attachment #195413 - Flags: review?(dougt)
Comment on attachment 196022 [details] [diff] [review]
v1.1

could you slap some comments on Inner().  Specifcally mention if it addrefs()
or not.

Also, i am not sure that is the best name for this method.
I think Peter probably changed the name from GetInner() to Inner() as an
indication of the fact that it does not return an already AddRef'd pointer. 
That's consistent with the way Gecko is coded.

I wonder if we want to obscure the method name to avoid conflicting with other
methods defined by some class.  Afterall, with these macros, the coder never
needs to really care about the name of these methods, variables, and so on.
Actually, changing it to Inner from GetInner is because it can't return null.
The fact that it returns a raw pointer instead of an already_AddRefed is because
it returns an non-addref'ed pointer. I can certainly document that if you want.
I think the name Inner comes from the inner/outer relationship in aggregation,
I'm not really sure what would be a better name. Any suggestion?
Status: NEW → ASSIGNED
Priority: -- → P4
Target Milestone: --- → mozilla1.9alpha
If consumers of these methods never need to explicitly call the methods or
implement them, then it would make sense to give them really obscure names to
avoid conflicts with other names used by classes.  Are there cases where code
would want to explicitly call Inner()?
Outside of the class, Inner should really only be called from the constructor
function.
Comment on attachment 196022 [details] [diff] [review]
v1.1

more correct documentation on this method can not hurt.  being consistent with
another area of code is a good thing, but we should let everyone konw what this
method should and shouldn't be used for.
Attachment #196022 - Flags: review?(dougt) → review+
I'm going to check this in tomorrow, here's what I ended up with:

+    /**                                                                     \
+     * Returns the nsISupports pointer of the inner object (aka the         \
+     * aggregatee). This pointer is really only useful to the outer object  \
+     * (aka the aggregator), which can use it to hold on to the inner       \
+     * object. Anything else wants the nsISupports pointer of the outer     \
+     * object (gotten by QI'ing inner or outer to nsISupports). This method \
+     * returns a non-addrefed pointer.                                      \
+     * @return the nsISupports pointer of the inner object                  \
+     */                                                                     \
+    nsISupports* InnerSupports(void) { return &fAggregated; }               \
How about InnerObject instead of InnerSupports?  Since you call it "inner
object" in the comments, this seems like a more natural name for the method :)
Checked in with InnerObject.
Status: ASSIGNED → RESOLVED
Closed: 19 years ago
Resolution: --- → FIXED
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: