#123679: Make setLookups really reentrant all_modules_cache_root iz_83282_root merged_to_visualvm_preview2 partial_reparse_t2b_c release61-m1_base versionability_89629_base_12
authorjtulach@netbeans.org
Wed, 16 Jan 2008 08:46:13 +0000
changeset 320ea7d449f606f
parent 319 b5d1bdca7357
child 321 f7f1a24b280a
#123679: Make setLookups really reentrant
openide.util/src/org/openide/util/lookup/ProxyLookup.java
openide.util/test/unit/src/org/openide/util/lookup/ProxyLookupTest.java
     1.1 --- a/openide.util/src/org/openide/util/lookup/ProxyLookup.java	Thu Jan 10 13:45:24 2008 +0000
     1.2 +++ b/openide.util/src/org/openide/util/lookup/ProxyLookup.java	Wed Jan 16 08:46:13 2008 +0000
     1.3 @@ -339,33 +339,47 @@
     1.4          /** initializes the results
     1.5           */
     1.6          private Result<T>[] initResults() {
     1.7 -            synchronized (this) {
     1.8 -                if (weakL.results != null) {
     1.9 -                    return weakL.results;
    1.10 -                }
    1.11 -            }
    1.12 -
    1.13 -            Lookup[] myLkps = getLookups(false);
    1.14 -            Result<T>[] arr = newResults(myLkps.length);
    1.15 -
    1.16 -            for (int i = 0; i < arr.length; i++) {
    1.17 -                arr[i] = myLkps[i].lookup(template);
    1.18 -            }
    1.19 -
    1.20 -            synchronized (this) {
    1.21 -                // some other thread might compute the result mean while. 
    1.22 -                // if not finish the computation yourself
    1.23 -                if (weakL.results != null) {
    1.24 -                    return weakL.results;
    1.25 +            BIG_LOOP: for (;;) {
    1.26 +                Lookup[] myLkps;
    1.27 +                synchronized (this) {
    1.28 +                    if (weakL.results != null) {
    1.29 +                        return weakL.results;
    1.30 +                    }
    1.31 +                    myLkps = getLookups(false);
    1.32                  }
    1.33  
    1.34 +                getLookups(false);
    1.35 +                Result<T>[] arr = newResults(myLkps.length);
    1.36 +
    1.37                  for (int i = 0; i < arr.length; i++) {
    1.38 -                    arr[i].addLookupListener(weakL);
    1.39 +                    arr[i] = myLkps[i].lookup(template);
    1.40                  }
    1.41  
    1.42 -                weakL.results = arr;
    1.43 +                synchronized (this) {
    1.44 +                    Lookup[] currentLkps = getLookups(false);
    1.45 +                    if (currentLkps.length != myLkps.length) {
    1.46 +                        continue BIG_LOOP;
    1.47 +                    }
    1.48 +                    for (int i = 0; i < currentLkps.length; i++) {
    1.49 +                        if (currentLkps[i] != myLkps[i]) {
    1.50 +                            continue BIG_LOOP;
    1.51 +                        }
    1.52 +                    }
    1.53 +                    
    1.54 +                    // some other thread might compute the result mean while. 
    1.55 +                    // if not finish the computation yourself
    1.56 +                    if (weakL.results != null) {
    1.57 +                        return weakL.results;
    1.58 +                    }
    1.59  
    1.60 -                return arr;
    1.61 +                    for (int i = 0; i < arr.length; i++) {
    1.62 +                        arr[i].addLookupListener(weakL);
    1.63 +                    }
    1.64 +
    1.65 +                    weakL.results = arr;
    1.66 +
    1.67 +                    return arr;
    1.68 +                }
    1.69              }
    1.70          }
    1.71  
     2.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/ProxyLookupTest.java	Thu Jan 10 13:45:24 2008 +0000
     2.2 +++ b/openide.util/test/unit/src/org/openide/util/lookup/ProxyLookupTest.java	Wed Jan 16 08:46:13 2008 +0000
     2.3 @@ -488,4 +488,47 @@
     2.4          
     2.5          assertEquals("C is overriden from removeLookupListener", Collections.emptyList(), res.allInstances());
     2.6      }
     2.7 +    
     2.8 +    
     2.9 +    public void testArrayIndexWithSetLookupAsInIssue123679() throws Exception {
    2.10 +        final ProxyLookup pl = new ProxyLookup();
    2.11 +        final int[] cnt = { 0 };
    2.12 +        
    2.13 +        class L extends Lookup {
    2.14 +            L[] set;
    2.15 +            Lookup l;
    2.16 +            Collection<? extends Serializable> res;
    2.17 +            
    2.18 +            public L(String s) {
    2.19 +                l = Lookups.singleton(s);
    2.20 +            }
    2.21 +            
    2.22 +            @Override
    2.23 +            public <T> T lookup(Class<T> clazz) {
    2.24 +                return l.lookup(clazz);
    2.25 +            }
    2.26 +
    2.27 +            @Override
    2.28 +            public <T> Result<T> lookup(Template<T> template) {
    2.29 +                cnt[0]++;
    2.30 +                if (set != null) {
    2.31 +                    pl.setLookups(set);
    2.32 +                    res = pl.lookupAll(Serializable.class);
    2.33 +                }
    2.34 +                Result<T> r = l.lookup(template);
    2.35 +                return r;
    2.36 +            }
    2.37 +        }
    2.38 +
    2.39 +        L[] now = { new L("A"), new L("B") };
    2.40 +        L[] old = { new L("C") };
    2.41 +        pl.setLookups(old);
    2.42 +        old[0].set = now;
    2.43 +        
    2.44 +        Result<String> res = pl.lookupResult(String.class);
    2.45 +        assertEquals("New items visible", 2, res.allItems().size());
    2.46 +        
    2.47 +        
    2.48 +        pl.setLookups(new L("X"), new L("Y"), new L("Z"));
    2.49 +    }
    2.50  }