Only access the observer field under the GLOBAL lock DeepWatch
authorJaroslav Tulach <jtulach@netbeans.org>
Sat, 02 Aug 2014 07:01:20 +0200
branchDeepWatch
changeset 785929f1192819c
parent 784 d41ae224c5d2
child 786 6a3b43d13a5c
Only access the observer field under the GLOBAL lock
json/src/main/java/org/apidesign/html/json/spi/Observers.java
json/src/main/java/org/apidesign/html/json/spi/Proto.java
     1.1 --- a/json/src/main/java/org/apidesign/html/json/spi/Observers.java	Sat Aug 02 06:45:55 2014 +0200
     1.2 +++ b/json/src/main/java/org/apidesign/html/json/spi/Observers.java	Sat Aug 02 07:01:20 2014 +0200
     1.3 @@ -57,7 +57,8 @@
     1.4      private final List<Watcher> watchers = new ArrayList<Watcher>();
     1.5      private final List<Ref> observers = new ArrayList<Ref>();
     1.6  
     1.7 -    private Observers() {
     1.8 +    Observers() {
     1.9 +        assert Thread.holdsLock(GLOBAL);
    1.10      }
    1.11      
    1.12      static void beginComputing(Proto p, String name) {
    1.13 @@ -78,41 +79,29 @@
    1.14          }        
    1.15      }
    1.16  
    1.17 -    static Observers accessingValue(Proto p, Observers observers, String propName) {
    1.18 +    static void accessingValue(Proto p, String propName) {
    1.19          synchronized (GLOBAL) {
    1.20              verifyUnlocked(p);
    1.21              for (Watcher w : GLOBAL) {
    1.22 -                if (observers == null) {
    1.23 -                    observers = new Observers();
    1.24 -                }
    1.25 -                observers.add(w, new Ref(w, propName));
    1.26 +                Observers mine = p.observers(true);
    1.27 +                mine.add(w, new Ref(w, propName));
    1.28              }
    1.29 -            return observers;
    1.30          }
    1.31      }
    1.32      
    1.33 -    static Observers finishComputing(Proto p, Observers mine) {
    1.34 +    static void finishComputing(Proto p) {
    1.35          synchronized (GLOBAL) {
    1.36              Watcher w = GLOBAL.pop();
    1.37              if (w.proto != p) {
    1.38                  throw new IllegalStateException("Inconsistency: " + w.proto + " != " + p);
    1.39              }
    1.40              if (w.prop != null) {
    1.41 -                if (mine == null) {
    1.42 -                    mine = new Observers();
    1.43 -                }
    1.44 +                Observers mine = p.observers(true);
    1.45                  mine.add(w);
    1.46              }
    1.47 -            return mine;
    1.48          }
    1.49      }
    1.50      
    1.51 -    static Watcher computing(Proto proto, String prop) {
    1.52 -        proto.getClass();
    1.53 -        prop.getClass();
    1.54 -        return new Watcher(proto, prop);
    1.55 -    }
    1.56 -    
    1.57      private static final class Ref extends WeakReference<Watcher> {
    1.58          private final String prop;
    1.59          
    1.60 @@ -126,7 +115,7 @@
    1.61              if (w == null) {
    1.62                  return null;
    1.63              }
    1.64 -            final Observers o = w.proto.observers();
    1.65 +            final Observers o = w.proto.observers(false);
    1.66              if (o == null) {
    1.67                  return null;
    1.68              }
    1.69 @@ -165,10 +154,14 @@
    1.70          watchers.add(w);
    1.71      }
    1.72  
    1.73 -    final void valueHasMutated(String propName) {
    1.74 +    static final void valueHasMutated(Proto p, String propName) {
    1.75          List<Watcher> mutated = new LinkedList<Watcher>();
    1.76          synchronized (GLOBAL) {
    1.77 -            Iterator<Ref> it = observers.iterator();
    1.78 +            Observers mine = p.observers(false);
    1.79 +            if (mine == null) {
    1.80 +                return;
    1.81 +            }
    1.82 +            Iterator<Ref> it = mine.observers.iterator();
    1.83              while (it.hasNext()) {
    1.84                  Ref ref = it.next();
    1.85                  if (ref.get() == null) {
    1.86 @@ -183,12 +176,12 @@
    1.87                  }
    1.88              }
    1.89          }
    1.90 -            for (Watcher w : mutated) {
    1.91 +        for (Watcher w : mutated) {
    1.92              w.proto.valueHasMutated(w.prop);
    1.93          }
    1.94      }
    1.95  
    1.96 -        void add(Watcher w, Ref r) {
    1.97 +    void add(Watcher w, Ref r) {
    1.98          Thread.holdsLock(GLOBAL);
    1.99          if (w == null) {
   1.100              return;
     2.1 --- a/json/src/main/java/org/apidesign/html/json/spi/Proto.java	Sat Aug 02 06:45:55 2014 +0200
     2.2 +++ b/json/src/main/java/org/apidesign/html/json/spi/Proto.java	Sat Aug 02 07:01:20 2014 +0200
     2.3 @@ -98,7 +98,7 @@
     2.4      }
     2.5      
     2.6      public void accessValue(String propName) {
     2.7 -        observers = Observers.accessingValue(this, observers, propName);
     2.8 +        Observers.accessingValue(this, propName);
     2.9      }
    2.10      
    2.11      /** Verifies the model is not locked otherwise throws an exception.
    2.12 @@ -112,7 +112,7 @@
    2.13       * unlocked state by calling this method.
    2.14       */
    2.15      public void releaseLock() {
    2.16 -        observers = Observers.finishComputing(this, observers);
    2.17 +        Observers.finishComputing(this);
    2.18      }
    2.19      
    2.20      /** Whenever model changes a property. It should notify the
    2.21 @@ -130,9 +130,7 @@
    2.22                  if (ko != null) {
    2.23                      ko.valueHasMutated(propName, null, null);
    2.24                  }
    2.25 -                if (observers != null) {
    2.26 -                    observers.valueHasMutated(propName);
    2.27 -                }
    2.28 +                Observers.valueHasMutated(Proto.this, propName);
    2.29              }
    2.30          });
    2.31      }
    2.32 @@ -160,9 +158,7 @@
    2.33                  if (ko != null) {
    2.34                      ko.valueHasMutated(propName, oldValue, newValue);
    2.35                  }
    2.36 -                if (observers != null) {
    2.37 -                    observers.valueHasMutated(propName);
    2.38 -                }
    2.39 +                Observers.valueHasMutated(Proto.this, propName);
    2.40              }
    2.41          });
    2.42      }
    2.43 @@ -454,7 +450,10 @@
    2.44          type.onChange(obj, index);
    2.45      }
    2.46  
    2.47 -    final Observers observers() {
    2.48 +    final Observers observers(boolean create) {
    2.49 +        if (create && observers == null) {
    2.50 +            observers = new Observers();
    2.51 +        }
    2.52          return observers;
    2.53      }
    2.54