<commit_before>/*
 * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 */
package org.opendaylight.controller.cluster.access.client;

import com.google.common.annotations.Beta;
import com.google.common.base.Verify;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
import java.util.concurrent.locks.StampedLock;

/**
 * A lock implementation which allows users to perform optimistic reads and validate them in a fashion similar
 * to {@link StampedLock}. In case a read is contented with a write, the read side will throw
 * an {@link InversibleLockException}, which the caller can catch and use to wait for the write to resolve.
 *
 * @author <NAME>
 */
@Beta
public final class InversibleLock {
    private static final AtomicReferenceFieldUpdater<InversibleLock, CountDownLatch> LATCH_UPDATER =
            AtomicReferenceFieldUpdater.newUpdater(InversibleLock.class, CountDownLatch.class, "latch");

    private final StampedLock lock = new StampedLock();
    private volatile CountDownLatch latch;

    /**
     * Return a stamp for read validation.
     *
     * @return A stamp, which can be used with {@link #validate(long)}.
     * @throws InversibleLockException if this lock is currently write-locked
     */
    public long optimisticRead() {
        while (true) {
            final long stamp = lock.tryOptimisticRead();
            if (stamp != 0) {
                return stamp;
            }

            // Write-locked. Read the corresponding latch and if present report an exception, which will propagate
            // and force release of locks.
            final CountDownLatch local = latch;
            if (local != null) {
                throw new InversibleLockException(latch);
            }

            // No latch present: retry optimistic lock
        }<commit_msg>BUG-5280: fix InversibleLock race<commit_after>/*
 * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 */
package org.opendaylight.controller.cluster.access.client;

import com.google.common.annotations.Beta;
import com.google.common.base.Verify;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
import java.util.concurrent.locks.StampedLock;

/**
 * A lock implementation which allows users to perform optimistic reads and validate them in a fashion similar
 * to {@link StampedLock}. In case a read is contented with a write, the read side will throw
 * an {@link InversibleLockException}, which the caller can catch and use to wait for the write to resolve.
 *
 * @author <NAME>
 */
@Beta
public final class InversibleLock {
    private static final AtomicReferenceFieldUpdater<InversibleLock, CountDownLatch> LATCH_UPDATER =
            AtomicReferenceFieldUpdater.newUpdater(InversibleLock.class, CountDownLatch.class, "latch");

    private final StampedLock lock = new StampedLock();
    private volatile CountDownLatch latch;

    /**
     * Return a stamp for read validation.
     *
     * @return A stamp, which can be used with {@link #validate(long)}.
     * @throws InversibleLockException if this lock is currently write-locked
     */
    public long optimisticRead() {
        while (true) {
            final long stamp = lock.tryOptimisticRead();
            if (stamp != 0) {
                return stamp;
            }

            // Write-locked. Read the corresponding latch and if present report an exception, which will propagate
            // and force release of locks.
            final CountDownLatch local = latch;
            if (local != null) {
                throw new InversibleLockException(local);
            }

            // No latch present: retry optimistic lock
        }
{'fraction_non_alphanumeric': 0.07848699763593381, 'fraction_numerical': 0.005200945626477541, 'mean_word_length': 2.9877474081055606, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5533891', 'n_tokens_mistral': 1136, 'n_tokens_neox': 1079, 'n_words': 405}