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 <[email protected]> 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: [email protected] For additional commands, e-mail: [email protected] For further information about the NetBeans mailing lists, visit: https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists
