From: Robert Varga Date: Sun, 1 Jan 2017 17:30:15 +0000 (+0100) Subject: BUG-7464: Eliminate {C,I}NodeBase X-Git-Tag: release/carbon~145 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=65bacf4e15665b41e84537ad3bf9adfe80c0d4d3;p=yangtools.git BUG-7464: Eliminate {C,I}NodeBase {C,I}NodeBase are just field holders for their sole subclasses. This arrangement comes from Scala, where the Base classes are implemented in Java and the rest of the code is in Scala. Remove both base classes by inlining the fields into CNode/INode. Change-Id: I349f1e1eeeb4301a1d6175ca5e16e7127ae1b540 Signed-off-by: Robert Varga --- diff --git a/third-party/triemap/src/main/java/org/opendaylight/yangtools/triemap/CNode.java b/third-party/triemap/src/main/java/org/opendaylight/yangtools/triemap/CNode.java index 3784ede483..ba6109eea7 100644 --- a/third-party/triemap/src/main/java/org/opendaylight/yangtools/triemap/CNode.java +++ b/third-party/triemap/src/main/java/org/opendaylight/yangtools/triemap/CNode.java @@ -15,13 +15,22 @@ */ package org.opendaylight.yangtools.triemap; -final class CNode extends CNodeBase { +import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; + +final class CNode extends MainNode { + @SuppressWarnings("rawtypes") + private static final AtomicIntegerFieldUpdater CSIZE_UPDATER = AtomicIntegerFieldUpdater.newUpdater( + CNode.class, "csize"); + private static final BasicNode[] EMPTY_ARRAY = new BasicNode[0]; + private static final int NO_SIZE = -1; final int bitmap; final BasicNode[] array; final Gen gen; + private volatile int csize = NO_SIZE; + private CNode(final Gen gen, final int bitmap, final BasicNode... array) { this.bitmap = bitmap; this.array = array; @@ -53,16 +62,17 @@ final class CNode extends CNodeBase { // this should only be called from within read-only snapshots @Override int cachedSize(final TrieMap ct) { - final int currsz = READ_SIZE(); - if (currsz != -1) { - return currsz; + int sz = csize; + if (sz == NO_SIZE) { + // We have not computed the size yet, do that now + sz = computeSize(ct); + if (!CSIZE_UPDATER.compareAndSet(this, NO_SIZE, sz)) { + // We have been pre-empted by some else: read the result + sz = csize; + } } - final int sz = computeSize(ct); - while (READ_SIZE () == -1) { - CAS_SIZE (-1, sz); - } - return READ_SIZE (); + return sz; } // lends itself towards being parallelizable by choosing @@ -87,7 +97,7 @@ final class CNode extends CNodeBase { if (elem instanceof SNode) { sz += 1; } else if (elem instanceof INode) { - sz += ((INode) elem).cachedSize (ct); + sz += ((INode) elem).cachedSize(ct); } i += 1; } diff --git a/third-party/triemap/src/main/java/org/opendaylight/yangtools/triemap/CNodeBase.java b/third-party/triemap/src/main/java/org/opendaylight/yangtools/triemap/CNodeBase.java deleted file mode 100644 index 71279440f2..0000000000 --- a/third-party/triemap/src/main/java/org/opendaylight/yangtools/triemap/CNodeBase.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * (C) Copyright 2016 Pantheon Technologies, s.r.o. and others. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.opendaylight.yangtools.triemap; - -import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; - -abstract class CNodeBase extends MainNode { - @SuppressWarnings("rawtypes") - private static final AtomicIntegerFieldUpdater CSIZE_UPDATER = - AtomicIntegerFieldUpdater.newUpdater(CNodeBase.class, "csize"); - - private volatile int csize = -1; - - final boolean CAS_SIZE(final int oldval, final int nval) { - return CSIZE_UPDATER.compareAndSet(this, oldval, nval); - } - - final int READ_SIZE() { - return csize; - } -} diff --git a/third-party/triemap/src/main/java/org/opendaylight/yangtools/triemap/INode.java b/third-party/triemap/src/main/java/org/opendaylight/yangtools/triemap/INode.java index 40bb592fec..2e8efe6524 100644 --- a/third-party/triemap/src/main/java/org/opendaylight/yangtools/triemap/INode.java +++ b/third-party/triemap/src/main/java/org/opendaylight/yangtools/triemap/INode.java @@ -16,8 +16,9 @@ package org.opendaylight.yangtools.triemap; import java.util.Optional; +import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; -final class INode extends INodeBase { +final class INode extends BasicNode { static final Object KEY_PRESENT = new Object (); static final Object KEY_ABSENT = new Object (); @@ -27,8 +28,17 @@ final class INode extends INodeBase { */ static final Object RESTART = new Object(); - INode(final Gen gen, final MainNode bn) { - super(gen, bn); + @SuppressWarnings("rawtypes") + private static final AtomicReferenceFieldUpdater MAINNODE_UPDATER = + AtomicReferenceFieldUpdater.newUpdater(INode.class, MainNode.class, "mainnode"); + + public final Gen gen; + + private volatile MainNode mainnode; + + INode(final Gen gen, final MainNode mainnode) { + this.gen = gen; + this.mainnode = mainnode; } MainNode gcasRead(final TrieMap ct) { @@ -36,7 +46,7 @@ final class INode extends INodeBase { } MainNode GCAS_READ(final TrieMap ct) { - MainNode m = /* READ */ READ(); + MainNode m = /* READ */ mainnode; MainNode prevval = /* READ */ m.READ_PREV(); if (prevval == null) { return m; @@ -61,12 +71,12 @@ final class INode extends INodeBase { if (prev instanceof FailedNode) { // try to commit to previous value FailedNode fn = (FailedNode) prev; - if (CAS(m, fn.READ_PREV())) { + if (MAINNODE_UPDATER.compareAndSet(this, m, fn.READ_PREV())) { return fn.READ_PREV(); } - // Tail recursion: return GCAS_Complete (/* READ */ READ(), ct); - m = /* READ */ READ(); + // Tail recursion: return GCAS_Complete (/* READ */ mainnode, ct); + m = /* READ */ mainnode; continue; } @@ -91,14 +101,14 @@ final class INode extends INodeBase { // try to abort m.CAS_PREV(prev, new FailedNode<>(prev)); - // Tail recursion: return GCAS_Complete(/* READ */ READ(), ct); - m = /* READ */ READ(); + // Tail recursion: return GCAS_Complete(/* READ */ mainnode, ct); + m = /* READ */ mainnode; } } private boolean GCAS(final MainNode old, final MainNode n, final TrieMap ct) { n.WRITE_PREV(old); - if (CAS(old, n)) { + if (MAINNODE_UPDATER.compareAndSet(this, old, n)) { GCAS_Complete(n, ct); return /* READ */ n.READ_PREV() == null; } diff --git a/third-party/triemap/src/main/java/org/opendaylight/yangtools/triemap/INodeBase.java b/third-party/triemap/src/main/java/org/opendaylight/yangtools/triemap/INodeBase.java deleted file mode 100644 index d74fe104a7..0000000000 --- a/third-party/triemap/src/main/java/org/opendaylight/yangtools/triemap/INodeBase.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * (C) Copyright 2016 Pantheon Technologies, s.r.o. and others. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.opendaylight.yangtools.triemap; - -import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; - -abstract class INodeBase extends BasicNode { - - @SuppressWarnings("rawtypes") - private static final AtomicReferenceFieldUpdater MAINNODE_UPDATER = - AtomicReferenceFieldUpdater.newUpdater(INodeBase.class, MainNode.class, "mainnode"); - - public final Gen gen; - - private volatile MainNode mainnode; - - INodeBase(final Gen generation, final MainNode mainnode) { - gen = generation; - this.mainnode = mainnode; - } - - final boolean CAS(final MainNode old, final MainNode n) { - return MAINNODE_UPDATER.compareAndSet(this, old, n); - } - - final MainNode READ() { - return mainnode; - } -}