Good points.

So what kind of solution do you propose.  Eliminating synchronization would
lead to __equalsCalc being corrupted in a multi-threaded
situation.  Keeping synchronization could lead to deadlock.  But if the
__equalsCalc state information is eliminated completely, there will be an
infinite loop problem and incorrect behavior.

I also want to point out the eliminating the equals() method and reverting
to Object.equals will break the tests.

The only solution is to make __equalsCalc a singleton static item in the
system and synchronize on it.  This would cause all generated equals logic
to wait....

Comments.

Rich Scheuerle
IBM WebSphere & Axis Web Services Development
512-838-5115  (IBM TL 678-5115)


                                                                                       
                                    
                      Eric.D.Friedman@Wel                                              
                                    
                      lsFargo.COM                To:       [EMAIL PROTECTED]     
                                    
                                                 cc:                                   
                                    
                      12/19/2002 04:14 PM        Subject:  RE: Q. about equals() in 
WSDL generated datatypes               
                      Please respond to                                                
                                    
                      axis-dev                                                         
                                    
                                                                                       
                                    
                                                                                       
                                    




I'm not Stephen, but I'd like to join this thread, as I think there's a
more
subtle problem here:

        // Stephen pointed out that we can never recurse back
        // because the method is syncronized...
        // or does syncronization know that I am recursing back
        // in the same thread.


The lock on the object with the synchronized method belongs to your thread,
so yes, it's possible to call a synchronized method recursively from within
a single thread, just as it's possible to invoke other synchronized methods
on that same object.

There's a bigger problem here, however:  synchronizing equals() methods in
this manner could result in thread deadlock if the objects in question are
deeply self referential.  Look at the calls to exchange.equals() and
number.equals() in the code below.  Now imagine that number has a
backreference to Phone and so its equals() method needs to invoke
Phone.equals() for the same reason that Phone's equals() method needs to
invoke number.equals().  Further suppose that two threads are active: one
invokes Phone.equals() while the other one calls number.equals() for some
other purpose.  Both threads will be deadlocked, since neither equals()
method can terminate until the other relinquishes the lock.

This is a danger inherent in code generation of this kind, and I suggest
that the right thing to do is to leave synchronization to the user of the
object -- it's just not possible (read: too expensive) to adequately handle
all of the cases that a tool like wsdl2java would have to deal with.

My unsolicited 2 cents,
Eric

-----Original Message-----
From: R J Scheuerle Jr [mailto:[EMAIL PROTECTED]]
Sent: Thursday, December 19, 2002 1:46 PM
To: [EMAIL PROTECTED]
Subject: RE: Q. about equals() in WSDL generated datatypes



Here's the full annotated code (for Phone).  I think the bug is that
__equalsCalc must be be reset before returning.  So I marked this as red.
Please evaluate and send me your comments.

Also think of the equals evaluating to different linked lists that contain
the same data.
Lets assume
A1->A2->A3  equals  B1->B2->B3

Now change the above slightly so the linked lists are circular.
A1->A2->A3  equals  B1->B2->B3
 ^-------+          ^--------+

They are still the same, and the equals method should return true.  This is
the case handled by __equalsCalc == obj

Now change the linked lists in a more devious way.

A1->A2->A3  equals  B1->B2->B3->A1->A2->A3
 ^-------+          ^-------------------+

In this situation, the equals method should return false since the looping
is different.  In the first case, the third object points back to the
initial object.  In the second case, the third element points to an object
other than the initial object.  This is the case handled by __equalsCalc !=
obj.


    private java.lang.Object __equalsCalc = null;
    public synchronized boolean equals(java.lang.Object obj) {
        // Return false immediately if wrong types
        if (!(obj instanceof Phone)) { __equalsCalc = null; return false;}

        // Return false if other object is null
        Phone other = (Phone) obj;
        if (obj == null) { __equalsCalc = null; return false; }

        // Return true if ==
        if (this == obj) { __equalsCalc = null;  return true; }

        // if equalsCalc is set, then we have looped
        // back to the "this" object.  Since the last time through
        // we set _equalsCal to the other object, return
        // true if the equalsCalc == the other object (the
        // the other object loops the same way) or return
        // false if the equalsCalc != the other object (the other
        // object does not loop the same way.)
        // Stephen pointed out that we can never recurse back
        // because the method is syncronized...
        // or does syncronization know that I am recursing back
        // in the same thread.
        if (__equalsCalc != null) {
            boolean rc = (_equalsCalc == obj);
            __equalsCalc = null;
            return rc;
        }

        // Flow to here indicates no recursion, so set _equalsCalc
        // to the other object in-case recursion occurs in the following
code.
        __equalsCalc = obj;
        boolean _equals;
        _equals = true &&
            areaCode == other.getAreaCode() &&
            ((exchange==null && other.getExchange()==null) ||
             (exchange!=null &&
              exchange.equals(other.getExchange()))) &&
            ((number==null && other.getNumber()==null) ||
             (number!=null &&
              number.equals(other.getNumber())));
        // Always reset __equalsCalc before returning.
        __equalsCalc = null;
        return _equals;
    }


Rich Scheuerle
IBM WebSphere & Axis Web Services Development
512-838-5115  (IBM TL 678-5115)




                      Glen Daniels

                      <gdaniels@macrome        To:
"'[EMAIL PROTECTED]'" <[EMAIL PROTECTED]>
                      dia.com>                 cc:

                                               Subject:  RE: Q. about
equals() in WSDL generated datatypes
                      12/19/2002 07:59

                      AM

                      Please respond to

                      axis-dev










Hi Rich!

Hm - I'm trying to imagine an example for when this would actually get
used, and having trouble coming up with one.  Could you elucidate?  I guess
what I'm really asking is why doesn't "if (this == obj) return true" catch
this?

--G

P.S.  Nice to see you back!

> -----Original Message-----
> From: R J Scheuerle Jr [mailto:[EMAIL PROTECTED]]
> Sent: Wednesday, December 18, 2002 8:27 PM
> To: [EMAIL PROTECTED]
> Subject: Re: Q. about equals() in WSDL generated datatypes
>
>
>
> Yes __equalsCal was meant to support equals for objects that
> had direct or
> indirectly references back to the object.
>
> Rich Scheuerle
> IBM WebSphere & Axis Web Services Development
> 512-838-5115  (IBM TL 678-5115)
>
>
>
>
>                       "Steve Loughran"
>
>                       <[EMAIL PROTECTED]        To:
> "axis-dev" <[EMAIL PROTECTED]>
>                       om>                      cc:
>
>                                                Subject:  Q.
> about equals() in WSDL generated datatypes
>                       12/18/2002 02:38
>
>                       PM
>
>                       Please respond to
>
>                       axis-dev
>
>
>
>
>
>
>
>
>
> So I'm staring at the equals() method that's been generated
> for me from a
> datatype
>
>     private java.lang.Object __equalsCalc = null;
>
>     public synchronized boolean equals(java.lang.Object obj) {
>         if (!(obj instanceof JobInfo)) return false;
>         JobInfo other = (JobInfo) obj;
>         if (obj == null) return false;
>         if (this == obj) return true;
>         if (__equalsCalc != null) {
>             return (__equalsCalc == obj);
>         }
>         __equalsCalc = obj;
>         ...tests
>         __equalsCalc = null;
>         return _equals;
>
>
> My q. is: what is all this __equalsCalc stuff? It implies
> that if there is
> a
> reentrant equality test then the test would return true while
> the test is
> ongoing, but since the method is synchronized, you'd be hard
> pressed to
> call
> equals() twice.
>
> Is that what the __equalsCalc is there for? To catch recursion?
>
> -steve
>
>
>
>
>







Reply via email to