You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@netbeans.apache.org by jt...@apache.org on 2019/05/04 11:05:12 UTC

[netbeans-html4j] 05/07: Documenting use of Fn.ref

This is an automated email from the ASF dual-hosted git repository.

jtulach pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans-html4j.git

commit 9f5b51df2e8db2e66f31085365b5d5b43d7ede83
Author: Jaroslav Tulach <ja...@apidesign.org>
AuthorDate: Sat May 4 10:40:56 2019 +0200

    Documenting use of Fn.ref
---
 .../netbeans/html/boot/fx/AbstractFXPresenter.java | 12 ++--
 .../html/boot/fx/AbstractFXPresenterTest.java      | 12 ++--
 .../java/org/netbeans/html/boot/impl/FnUtils.java  |  4 +-
 .../html/boot/impl/JavaScriptProcesor.java         | 10 +--
 .../netbeans/html/boot/spi/FallbackIdentity.java   |  4 +-
 .../main/java/org/netbeans/html/boot/spi/Fn.java   | 77 ++++++++++++++++++----
 .../html/boot/spi/FallbackIdentityTest.java        | 19 +++---
 .../java/org/netbeans/html/ko4j/CacheObjs.java     |  4 +-
 .../main/java/org/netbeans/html/ko4j/Knockout.java |  2 +-
 .../main/java/org/netbeans/html/ko4j/MapObjs.java  | 18 ++---
 10 files changed, 107 insertions(+), 55 deletions(-)

diff --git a/boot-fx/src/main/java/org/netbeans/html/boot/fx/AbstractFXPresenter.java b/boot-fx/src/main/java/org/netbeans/html/boot/fx/AbstractFXPresenter.java
index 26e1329..0e1737a 100644
--- a/boot-fx/src/main/java/org/netbeans/html/boot/fx/AbstractFXPresenter.java
+++ b/boot-fx/src/main/java/org/netbeans/html/boot/fx/AbstractFXPresenter.java
@@ -50,7 +50,7 @@ import org.netbeans.html.boot.spi.Fn;
  * @author Jaroslav Tulach
  */
 public abstract class AbstractFXPresenter implements Fn.Presenter,
-Fn.KeepAlive, Fn.ToJavaScript, Fn.FromJavaScript, Executor, Cloneable, Fn.Identity {
+Fn.KeepAlive, Fn.ToJavaScript, Fn.FromJavaScript, Executor, Cloneable, Fn.Ref<AbstractFXPresenter> {
     static final Logger LOG = Logger.getLogger(FXPresenter.class.getName());
     protected static int cnt;
     protected Runnable onLoad;
@@ -605,7 +605,7 @@ Fn.KeepAlive, Fn.ToJavaScript, Fn.FromJavaScript, Executor, Cloneable, Fn.Identi
     }
 
     @Override
-    public synchronized Fn.Identity id() {
+    public synchronized Fn.Ref<AbstractFXPresenter> reference() {
         if (id == null) {
             id = new Id(this);
         }
@@ -613,22 +613,22 @@ Fn.KeepAlive, Fn.ToJavaScript, Fn.FromJavaScript, Executor, Cloneable, Fn.Identi
     }
 
     @Override
-    public Fn.Presenter presenter() {
+    public AbstractFXPresenter presenter() {
         return this;
     }
 
-    private static final class Id extends WeakReference<AbstractFXPresenter> implements Fn.Identity {
+    private static final class Id extends WeakReference<AbstractFXPresenter> implements Fn.Ref<AbstractFXPresenter> {
         Id(AbstractFXPresenter referent) {
             super(referent);
         }
 
         @Override
-        public Fn.Identity id() {
+        public Fn.Ref<AbstractFXPresenter> reference() {
             return this;
         }
 
         @Override
-        public Fn.Presenter presenter() {
+        public AbstractFXPresenter presenter() {
             return get();
         }
     }
diff --git a/boot-fx/src/test/java/org/netbeans/html/boot/fx/AbstractFXPresenterTest.java b/boot-fx/src/test/java/org/netbeans/html/boot/fx/AbstractFXPresenterTest.java
index 7176dbf..1c3a1cc 100644
--- a/boot-fx/src/test/java/org/netbeans/html/boot/fx/AbstractFXPresenterTest.java
+++ b/boot-fx/src/test/java/org/netbeans/html/boot/fx/AbstractFXPresenterTest.java
@@ -53,14 +53,16 @@ public class AbstractFXPresenterTest {
             }
         };
 
-        Fn.Identity id1 = Fn.id(p1);
-        Fn.Identity id12 = Fn.id(p1);
+        Fn.Ref<?> id1 = Fn.ref(p1);
+        Fn.Ref<?> id12 = Fn.ref(p1);
 
         assertSame(id1, id12);
         assertEquals(id1, id12);
+        assertSame(p1, id1.presenter());
 
-        Fn.Identity id2 = Fn.id(p2);
-        Fn.Identity id22 = Fn.id(p2);
+        Fn.Ref<?> id2 = Fn.ref(p2);
+        Fn.Ref<?> id22 = Fn.ref(p2);
+        assertSame(p2, id2.presenter());
 
         assertSame(id2, id22);
         assertEquals(id2, id22);
@@ -72,6 +74,6 @@ public class AbstractFXPresenterTest {
         NbTestCase.assertGC("Presenter can disappear", ref1);
 
         AbstractFXPresenter p2Clone = p2.clone();
-        Assert.assertNotEquals(p2.id(), p2Clone.id());
+        Assert.assertNotEquals(p2.reference(), p2Clone.reference());
     }
 }
diff --git a/boot/src/main/java/org/netbeans/html/boot/impl/FnUtils.java b/boot/src/main/java/org/netbeans/html/boot/impl/FnUtils.java
index 02e753f..ed390dd 100644
--- a/boot/src/main/java/org/netbeans/html/boot/impl/FnUtils.java
+++ b/boot/src/main/java/org/netbeans/html/boot/impl/FnUtils.java
@@ -651,8 +651,8 @@ public final class FnUtils {
             if (name.equals(Fn.Presenter.class.getName())) {
                 return Fn.Presenter.class;
             }
-            if (name.equals(Fn.Identity.class.getName())) {
-                return Fn.Identity.class;
+            if (name.equals(Fn.Ref.class.getName())) {
+                return Fn.Ref.class;
             }
             if (name.equals(Fn.ToJavaScript.class.getName())) {
                 return Fn.ToJavaScript.class;
diff --git a/boot/src/main/java/org/netbeans/html/boot/impl/JavaScriptProcesor.java b/boot/src/main/java/org/netbeans/html/boot/impl/JavaScriptProcesor.java
index 5e421ae..9344809 100644
--- a/boot/src/main/java/org/netbeans/html/boot/impl/JavaScriptProcesor.java
+++ b/boot/src/main/java/org/netbeans/html/boot/impl/JavaScriptProcesor.java
@@ -400,18 +400,18 @@ public final class JavaScriptProcesor extends AbstractProcessor {
             source.append("package ").append(pkgName).append(";\n");
             source.append("public final class $JsCallbacks$ {\n");
             source.append("  static final $JsCallbacks$ VM = new $JsCallbacks$(null);\n");
-            source.append("  private final org.netbeans.html.boot.spi.Fn.Identity id;\n");
+            source.append("  private final org.netbeans.html.boot.spi.Fn.Ref<?> ref;\n");
             source.append("  private $JsCallbacks$ next;\n");
             source.append("  private $JsCallbacks$(org.netbeans.html.boot.spi.Fn.Presenter p) {\n");
-            source.append("    this.id = org.netbeans.html.boot.spi.Fn.id(p);\n");
+            source.append("    this.ref = org.netbeans.html.boot.spi.Fn.ref(p);\n");
             source.append("  }\n");
             source.append("  synchronized final $JsCallbacks$ current() {\n");
             source.append("    org.netbeans.html.boot.spi.Fn.Presenter now = org.netbeans.html.boot.spi.Fn.activePresenter();\n");
             source.append("    $JsCallbacks$ thiz = this;\n");
             source.append("    $JsCallbacks$ prev = null;\n");
             source.append("    for (;;) {\n");
-            source.append("      if (thiz.id != null) {\n");
-            source.append("        org.netbeans.html.boot.spi.Fn.Presenter thizPresenter = thiz.id.presenter();\n");
+            source.append("      if (thiz.ref != null) {\n");
+            source.append("        org.netbeans.html.boot.spi.Fn.Presenter thizPresenter = thiz.ref.presenter();\n");
             source.append("        if (thizPresenter == null) {\n");
             source.append("          if (prev != null) {\n");
             source.append("            prev.next = thiz.next;\n");
@@ -497,7 +497,7 @@ public final class JavaScriptProcesor extends AbstractProcessor {
             sep = ", ";
         }
         source.append(") throws Throwable {\n");
-        source.append("    org.netbeans.html.boot.spi.Fn.Presenter p = id.presenter(); \n");
+        source.append("    org.netbeans.html.boot.spi.Fn.Presenter p = ref.presenter(); \n");
         source.append(convert);
         if (useTryResources()) {
             source.append("    try (java.io.Closeable a = org.netbeans.html.boot.spi.Fn.activate(p)) { \n");
diff --git a/boot/src/main/java/org/netbeans/html/boot/spi/FallbackIdentity.java b/boot/src/main/java/org/netbeans/html/boot/spi/FallbackIdentity.java
index a1d0cfc..087842c 100644
--- a/boot/src/main/java/org/netbeans/html/boot/spi/FallbackIdentity.java
+++ b/boot/src/main/java/org/netbeans/html/boot/spi/FallbackIdentity.java
@@ -20,7 +20,7 @@ package org.netbeans.html.boot.spi;
 
 import java.lang.ref.WeakReference;
 
-final class FallbackIdentity extends WeakReference<Fn.Presenter> implements Fn.Identity {
+final class FallbackIdentity extends WeakReference<Fn.Presenter> implements Fn.Ref {
     private final int hashCode;
 
     FallbackIdentity(Fn.Presenter p) {
@@ -29,7 +29,7 @@ final class FallbackIdentity extends WeakReference<Fn.Presenter> implements Fn.I
     }
 
     @Override
-    public Fn.Identity id() {
+    public Fn.Ref reference() {
         return this;
     }
 
diff --git a/boot/src/main/java/org/netbeans/html/boot/spi/Fn.java b/boot/src/main/java/org/netbeans/html/boot/spi/Fn.java
index f98abde..1a613ea 100644
--- a/boot/src/main/java/org/netbeans/html/boot/spi/Fn.java
+++ b/boot/src/main/java/org/netbeans/html/boot/spi/Fn.java
@@ -23,6 +23,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
+import java.lang.ref.WeakReference;
 import java.net.URL;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -38,7 +39,7 @@ import org.netbeans.html.boot.impl.FnContext;
  * @author Jaroslav Tulach
  */
 public abstract class Fn {
-    private final Identity presenter;
+    private final Ref presenter;
     
     /**
      * @deprecated Ineffective as of 0.6. 
@@ -56,7 +57,7 @@ public abstract class Fn {
      * @since 0.6 
      */
     protected Fn(Presenter presenter) {
-        this.presenter = id(presenter);
+        this.presenter = ref(presenter);
     }
 
     /** True, if currently active presenter is the same as presenter this
@@ -177,12 +178,25 @@ public abstract class Fn {
         return FnContext.activate(p);
     }
 
-    public static Identity id(final Presenter p) {
+    /** Obtains a (usually {@linkplain WeakReference weak}) reference to
+     * the presenter. Such reference is suitable for embedding in various long
+     * living structures with a life-cycle that may outspan the one of presenter.
+     *
+     * @param p the presenter
+     * @return reference to the presenter, {@code null} only if {@code p} is {@code null}
+     * @since 1.6.1
+     * @see Ref
+     */
+    public static Ref<?> ref(final Presenter p) {
         if (p == null) {
             return null;
         }
-        if (p instanceof Identity) {
-            return ((Identity) p).id();
+        if (p instanceof Ref<?>) {
+            Ref<?> r = ((Ref<?>) p).reference();
+            if (r == null) {
+                throw new NullPointerException();
+            }
+            return r;
         }
         return new FallbackIdentity(p);
     }
@@ -332,17 +346,52 @@ public abstract class Fn {
         public Fn defineFn(String code, String[] names, boolean[] keepAlive);
     }
 
-    public interface Identity {
-        public Identity id();
-        public Presenter presenter();
+    /**
+     * Reference to a {@link Presenter}.Each implementation of a {@link Presenter}
+     * may choose a way to reference itself (usually in a {@linkplain WeakReference weak way})
+     * effectively. Various code that needs to hold a reference to a presenter
+     * is then encouraged to obtain such reference via {@link Fn#ref(org.netbeans.html.boot.spi.Fn.Presenter)}
+     * call and hold on to it. Holding a reference to an instance of {@link Presenter}
+     * is discouraged as it may lead to memory leaks.
+     * <p>
+     * Presenters willing to to represent a reference to itself effectively shall
+     * also implement the {@link Ref} interface and return reasonable reference
+     * from the {@link #reference()} method.
+     *
+     * @param <P> the type of the presenter
+     * @see Fn#ref(org.netbeans.html.boot.spi.Fn.Presenter)
+     * @since 1.6.1
+     */
+    public interface Ref<P extends Presenter> {
+        /** Creates a reference to a presenter.
+         * Rather than calling this method directly, call {@link Fn#ref(org.netbeans.html.boot.spi.Fn.Presenter)}.
+         * @return a (weak) reference to the associated presenter
+         */
+        public Ref<P> reference();
+
+        /** The associated presenter.
+         *
+         * @return the presenter or {@code null}, if it has been GCed meanwhile
+         */
+        public P presenter();
+
+        /** Reference must properly implement {@link #hashCode} and {@link #equals}.
+         *
+         * @return proper hashcode
+         */
         @Override
         public int hashCode();
+
+        /** Reference must properly implement {@link #hashCode} and {@link #equals}.
+         *
+         * @return proper equals result
+         */
         @Override
         public boolean equals(Object obj);
     }
 
     private static class Preload extends Fn {
-        private static Map<String, Set<Identity>> LOADED;
+        private static Map<String, Set<Ref>> LOADED;
         private final Fn fn;
         private final String resource;
         private final Class<?> caller;
@@ -367,18 +416,18 @@ public abstract class Fn {
         }
 
         private void loadResource() throws Exception {
-            Identity id = super.presenter;
+            Ref id = super.presenter;
             if (id == null) {
-                id = id(FnContext.currentPresenter(false));
+                id = ref(FnContext.currentPresenter(false));
             }
             Fn.Presenter realPresenter = id == null ? null : id.presenter();
             if (realPresenter != null) {
                 if (LOADED == null) {
-                    LOADED = new HashMap<String, Set<Identity>>();
+                    LOADED = new HashMap<String, Set<Ref>>();
                 }
-                Set<Identity> there = LOADED.get(resource);
+                Set<Ref> there = LOADED.get(resource);
                 if (there == null) {
-                    there = new HashSet<Identity>();
+                    there = new HashSet<Ref>();
                     LOADED.put(resource, there);
                 }
                 if (there.add(id)) {
diff --git a/boot/src/test/java/org/netbeans/html/boot/spi/FallbackIdentityTest.java b/boot/src/test/java/org/netbeans/html/boot/spi/FallbackIdentityTest.java
index 760531f..6a57522 100644
--- a/boot/src/test/java/org/netbeans/html/boot/spi/FallbackIdentityTest.java
+++ b/boot/src/test/java/org/netbeans/html/boot/spi/FallbackIdentityTest.java
@@ -24,10 +24,6 @@ import java.lang.ref.WeakReference;
 import java.net.URL;
 import org.netbeans.junit.NbTestCase;
 import static org.testng.Assert.*;
-import org.testng.annotations.AfterClass;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
 public class FallbackIdentityTest {
@@ -52,8 +48,8 @@ public class FallbackIdentityTest {
             }
         };
 
-        Fn.Identity id1 = Fn.id(p);
-        Fn.Identity id2 = Fn.id(p);
+        Fn.Ref<?> id1 = Fn.ref(p);
+        Fn.Ref<?> id2 = Fn.ref(p);
 
         assertNotSame(id1, id2);
         assertEquals(id1, id2);
@@ -66,7 +62,7 @@ public class FallbackIdentityTest {
 
     @Test
     public void testPresenterCanProvideItsOwnIdentity() {
-        class IdPresenter implements Fn.Presenter, Fn.Identity {
+        class IdPresenter implements Fn.Presenter, Fn.Ref {
             @Override
             public Fn defineFn(String code, String... names) {
                 return null;
@@ -81,7 +77,7 @@ public class FallbackIdentityTest {
             }
 
             @Override
-            public Fn.Identity id() {
+            public Fn.Ref reference() {
                 return this;
             }
 
@@ -92,6 +88,11 @@ public class FallbackIdentityTest {
         }
         IdPresenter p = new IdPresenter();
 
-        assertSame(p, Fn.id(p));
+        assertSame(p, Fn.ref(p));
+    }
+
+    @Test
+    public void nullYieldsNullReference() {
+        assertNull(Fn.ref(null));
     }
 }
diff --git a/ko4j/src/main/java/org/netbeans/html/ko4j/CacheObjs.java b/ko4j/src/main/java/org/netbeans/html/ko4j/CacheObjs.java
index 8b969ff..e1aea1a 100644
--- a/ko4j/src/main/java/org/netbeans/html/ko4j/CacheObjs.java
+++ b/ko4j/src/main/java/org/netbeans/html/ko4j/CacheObjs.java
@@ -25,14 +25,14 @@ final class CacheObjs {
     /* both @GuardedBy CacheObjs.class */
     private static final CacheObjs[] list = new CacheObjs[16];
     private static int listAt = 0;
-    private final Fn.Identity ref;
+    private final Fn.Ref<?> ref;
 
     /* both @GuardedBy presenter single threaded access */
     private Object[] jsObjects;
     private int jsIndex;
 
     private CacheObjs(Fn.Presenter p) {
-        this.ref = Fn.id(p);
+        this.ref = Fn.ref(p);
     }
 
     Fn.Presenter get() {
diff --git a/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java b/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java
index 883d27b..1e826d8 100644
--- a/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java
+++ b/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java
@@ -155,7 +155,7 @@ final class Knockout  {
             if (obj == null) {
                 return null;
             } else {
-                return ((Fn.Identity) obj).presenter();
+                return ((Fn.Ref) obj).presenter();
             }
         }
     }
diff --git a/ko4j/src/main/java/org/netbeans/html/ko4j/MapObjs.java b/ko4j/src/main/java/org/netbeans/html/ko4j/MapObjs.java
index c2b996e..56a56bc 100644
--- a/ko4j/src/main/java/org/netbeans/html/ko4j/MapObjs.java
+++ b/ko4j/src/main/java/org/netbeans/html/ko4j/MapObjs.java
@@ -24,7 +24,7 @@ import net.java.html.json.Models;
 import org.netbeans.html.boot.spi.Fn;
 
 final class MapObjs {
-    private static Fn.Identity onlyPresenter;
+    private static Fn.Ref onlyPresenter;
     private static boolean usePresenter;
 
     static {
@@ -38,11 +38,11 @@ final class MapObjs {
 
     private final List<Object> all;
 
-    private MapObjs(Fn.Identity id1, Object js) {
+    private MapObjs(Fn.Ref id1, Object js) {
         this.all = Models.asList(id1, js);
     }
 
-    private MapObjs(Fn.Identity id1, Object js1, Fn.Identity id2, Object js2) {
+    private MapObjs(Fn.Ref id1, Object js1, Fn.Ref id2, Object js2) {
         this.all = Models.asList(id1, js1, id2, js2);
     }
 
@@ -62,9 +62,9 @@ final class MapObjs {
                 }
             }
             if (now == null) {
-                return new MapObjs(Fn.id(key), js);
+                return new MapObjs(Fn.ref(key), js);
             } else {
-                return new MapObjs(onlyPresenter, now, Fn.id(key), js);
+                return new MapObjs(onlyPresenter, now, Fn.ref(key), js);
             }
         }
     }
@@ -101,15 +101,15 @@ final class MapObjs {
                 return this;
             }
         }
-        all.add(Fn.id(key));
+        all.add(Fn.ref(key));
         all.add(js);
         return this;
     }
 
     boolean isSameKey(int index, Fn.Presenter key) {
         Object at = all.get(index);
-        if (at instanceof Fn.Identity) {
-            at = ((Fn.Identity)at).presenter();
+        if (at instanceof Fn.Ref) {
+            at = ((Fn.Ref)at).presenter();
         }
         return at == key;
     }
@@ -138,6 +138,6 @@ final class MapObjs {
     }
 
     private static void setOnlyPresenter(Fn.Presenter p) {
-        onlyPresenter = Fn.id(p);
+        onlyPresenter = Fn.ref(p);
     }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists