2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.controller.netconf.confignetconfconnector.osgi;
11 import java.lang.ref.SoftReference;
12 import java.util.concurrent.atomic.AtomicReference;
14 import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
15 import org.slf4j.Logger;
16 import org.slf4j.LoggerFactory;
18 public class YangStoreServiceImpl implements YangStoreService {
19 private static final Logger LOG = LoggerFactory.getLogger(YangStoreServiceImpl.class);
22 * This is a rather interesting locking model. We need to guard against both the
23 * cache expiring from GC and being invalidated by schema context change. The
24 * context can change while we are doing processing, so we do not want to block
25 * it, so no synchronization can happen on the methods.
27 * So what we are doing is the following:
29 * We synchronize with GC as usual, using a SoftReference.
31 * The atomic reference is used to synchronize with {@link #refresh()}, e.g. when
32 * refresh happens, it will push a SoftReference(null), e.g. simulate the GC. Now
33 * that may happen while the getter is already busy acting on the old schema context,
34 * so it needs to understand that a refresh has happened and retry. To do that, it
35 * attempts a CAS operation -- if it fails, in knows that the SoftReference has
36 * been replaced and thus it needs to retry.
38 * Note that {@link #getYangStoreSnapshot()} will still use synchronize() internally
39 * to stop multiple threads doing the same work.
41 private final AtomicReference<SoftReference<YangStoreSnapshotImpl>> ref = new AtomicReference<>(new SoftReference<YangStoreSnapshotImpl>(null));
42 private final SchemaContextProvider service;
44 public YangStoreServiceImpl(final SchemaContextProvider service) {
45 this.service = service;
49 public synchronized YangStoreSnapshotImpl getYangStoreSnapshot() throws YangStoreException {
50 SoftReference<YangStoreSnapshotImpl> r = ref.get();
51 YangStoreSnapshotImpl ret = r.get();
54 // We need to be compute a new value
55 ret = new YangStoreSnapshotImpl(service.getSchemaContext());
57 if (!ref.compareAndSet(r, new SoftReference<>(ret))) {
58 LOG.debug("Concurrent refresh detected, recomputing snapshot");
68 * Called when schema context changes, invalidates cache.
70 public void refresh() {
71 ref.set(new SoftReference<YangStoreSnapshotImpl>(null));