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;
13 import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
14 import org.slf4j.Logger;
15 import org.slf4j.LoggerFactory;
17 public class YangStoreServiceImpl implements YangStoreService {
18 private static final Logger LOG = LoggerFactory.getLogger(YangStoreServiceImpl.class);
21 * This is a rather interesting locking model. We need to guard against both the
22 * cache expiring from GC and being invalidated by schema context change. The
23 * context can change while we are doing processing, so we do not want to block
24 * it, so no synchronization can happen on the methods.
26 * So what we are doing is the following:
28 * We synchronize with GC as usual, using a SoftReference.
30 * The atomic reference is used to synchronize with {@link #refresh()}, e.g. when
31 * refresh happens, it will push a SoftReference(null), e.g. simulate the GC. Now
32 * that may happen while the getter is already busy acting on the old schema context,
33 * so it needs to understand that a refresh has happened and retry. To do that, it
34 * attempts a CAS operation -- if it fails, in knows that the SoftReference has
35 * been replaced and thus it needs to retry.
37 * Note that {@link #getYangStoreSnapshot()} will still use synchronize() internally
38 * to stop multiple threads doing the same work.
40 private final AtomicReference<SoftReference<YangStoreSnapshotImpl>> ref = new AtomicReference<>(new SoftReference<YangStoreSnapshotImpl>(null));
41 private final SchemaContextProvider service;
43 public YangStoreServiceImpl(final SchemaContextProvider service) {
44 this.service = service;
48 public synchronized YangStoreSnapshotImpl getYangStoreSnapshot() throws YangStoreException {
49 SoftReference<YangStoreSnapshotImpl> r = ref.get();
50 YangStoreSnapshotImpl ret = r.get();
53 // We need to be compute a new value
54 ret = new YangStoreSnapshotImpl(service.getSchemaContext());
56 if (!ref.compareAndSet(r, new SoftReference<>(ret))) {
57 LOG.debug("Concurrent refresh detected, recomputing snapshot");
67 * Called when schema context changes, invalidates cache.
69 public void refresh() {
70 ref.set(new SoftReference<YangStoreSnapshotImpl>(null));