permits LazyAugmentationModification, LazyDataObjectModification {
private static final Logger LOG = LoggerFactory.getLogger(AbstractDataObjectModification.class);
private static final VarHandle MODIFICATION_TYPE;
+ private static final VarHandle MODIFIED_CHILDREN;
static {
final var lookup = MethodHandles.lookup();
try {
MODIFICATION_TYPE = lookup.findVarHandle(AbstractDataObjectModification.class, "modificationType",
ModificationType.class);
+ MODIFIED_CHILDREN = lookup.findVarHandle(AbstractDataObjectModification.class, "modifiedChildren",
+ ImmutableList.class);
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new ExceptionInInitializerError(e);
}
final @NonNull PathArgument identifier;
final @NonNull N codec;
- private volatile ImmutableList<AbstractDataObjectModification<?, ?>> childNodesCache;
+ @SuppressWarnings("unused")
+ private volatile ImmutableList<AbstractDataObjectModification<?, ?>> modifiedChildren;
@SuppressWarnings("unused")
private volatile ModificationType modificationType;
private volatile @Nullable T dataBefore;
@Override
public final ImmutableList<AbstractDataObjectModification<?, ?>> getModifiedChildren() {
- var local = childNodesCache;
- if (local == null) {
- childNodesCache = local = createModifiedChilden(codec, domData, domChildNodes());
- }
- return local;
+ final var local = (ImmutableList<AbstractDataObjectModification<?, ?>>) MODIFIED_CHILDREN.getAcquire(this);
+ return local != null ? local : loadModifiedChilden();
}
@Override
.collect(Collectors.toList());
}
+ @SuppressWarnings("unchecked")
+ private @NonNull ImmutableList<AbstractDataObjectModification<?, ?>> loadModifiedChilden() {
+ final var builder = ImmutableList.<AbstractDataObjectModification<?, ?>>builder();
+ populateList(builder, codec, domData, domChildNodes());
+ final var computed = builder.build();
+ // Non-trivial return: use CAS to ensure we reuse concurrent loads
+ final var witness = MODIFIED_CHILDREN.compareAndExchangeRelease(this, null, computed);
+ return witness == null ? computed : (ImmutableList<AbstractDataObjectModification<?, ?>>) witness;
+ }
+
@SuppressWarnings("unchecked")
private <C extends DataObject> Stream<LazyDataObjectModification<C>> streamModifiedChildren(
final Class<C> childType) {
};
}
- private static @NonNull ImmutableList<AbstractDataObjectModification<?, ?>> createModifiedChilden(
- final CommonDataObjectCodecTreeNode<?> parentCodec, final DataTreeCandidateNode parent,
- final Collection<DataTreeCandidateNode> children) {
- final var result = ImmutableList.<AbstractDataObjectModification<?, ?>>builder();
- populateList(result, parentCodec, parent, children);
- return result.build();
- }
-
private static void populateList(final ImmutableList.Builder<AbstractDataObjectModification<?, ?>> result,
final CommonDataObjectCodecTreeNode<?> parentCodec, final DataTreeCandidateNode parent,
final Collection<DataTreeCandidateNode> children) {