All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sleepycat.je.latch.SharedLatchImpl Maven / Gradle / Ivy

The newest version!
/*-
 * Copyright (C) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
 *
 * This file was distributed by Oracle as part of a version of Oracle Berkeley
 * DB Java Edition made available at:
 *
 * http://www.oracle.com/technetwork/database/database-technologies/berkeleydb/downloads/index.html
 *
 * Please see the LICENSE file included in the top-level directory of the
 * appropriate version of Oracle Berkeley DB Java Edition for a copy of the
 * license and additional information.
 */

package com.sleepycat.je.latch;

import static com.sleepycat.je.EnvironmentFailureException.unexpectedState;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import com.sleepycat.je.ThreadInterruptedException;
import com.sleepycat.je.dbi.EnvironmentImpl;
import com.sleepycat.je.utilint.StatGroup;

@SuppressWarnings("serial")
public class SharedLatchImpl extends ReentrantReadWriteLock
    implements SharedLatch {

    private final LatchContext context;
    private OwnerInfo lastOwnerInfo;

    SharedLatchImpl(final boolean fair, final LatchContext context) {
        super(fair);
        this.context = context;
    }

    @Override
    public boolean isExclusiveOnly() {
        return false;
    }

    @Override
    public void acquireExclusive() {
        doAcquireExclusive(false /*noWait*/);
    }

    @Override
    public boolean acquireExclusiveNoWait() {
        return doAcquireExclusive(true /*noWait*/);
    }

    private boolean doAcquireExclusive(final boolean noWait) {
        if (isWriteLockedByCurrentThread() || (getReadHoldCount() > 0)) {
            throw unexpectedState(
                context.getEnvImplForFatalException(),
                "Latch already held: " + debugString());
        }

        if (noWait) {
            if (!writeLock().tryLock()) {
                return false;
            }
        } else if (LatchSupport.INTERRUPTIBLE_WITH_TIMEOUT) {
            try {
                if (!writeLock().tryLock(
                    context.getLatchTimeoutMs(), TimeUnit.MILLISECONDS)) {
                    throw LatchSupport.handleTimeout(this, context);
                }
            } catch (InterruptedException e) {
                throw new ThreadInterruptedException(
                    context.getEnvImplForFatalException(), e);
            }
        } else {
            writeLock().lock();
        }

        if (LatchSupport.TRACK_LATCHES) {
            LatchSupport.trackAcquire(this, context);
        }
        if (LatchSupport.CAPTURE_OWNER) {
            lastOwnerInfo = new OwnerInfo(context);
        }
        assert EnvironmentImpl.maybeForceYield();
        return true;
    }

    @Override
    public void acquireShared() {
        if (isWriteLockedByCurrentThread()) {
            throw unexpectedState(
                context.getEnvImplForFatalException(),
                "Latch already held exclusively: " + debugString());
        }

        if (getReadHoldCount() > 0) {
            throw unexpectedState(
                context.getEnvImplForFatalException(),
                "Latch already held non-exclusively: " + debugString());
        }

        if (LatchSupport.INTERRUPTIBLE_WITH_TIMEOUT) {
            try {
                if (!readLock().tryLock(
                    context.getLatchTimeoutMs(), TimeUnit.MILLISECONDS)) {
                    throw LatchSupport.handleTimeout(this, context);
                }
            } catch (InterruptedException e) {
                throw new ThreadInterruptedException(
                    context.getEnvImplForFatalException(), e);
            }
        } else {
            readLock().lock();
        }
        if (LatchSupport.TRACK_LATCHES) {
            LatchSupport.trackAcquire(this, context);
        }
        assert EnvironmentImpl.maybeForceYield();
    }

    @Override
    public void release() {
        doRelease(false /*ifOwner*/);
    }

    @Override
    public void releaseIfOwner() {
        doRelease(true /*ifOwner*/);
    }

    private void doRelease(final boolean ifOwner) {
        if (getReadHoldCount() > 0) {
            if (LatchSupport.TRACK_LATCHES) {
                LatchSupport.trackRelease(this, context);
            }
            readLock().unlock();
            return;
        }
        if (isWriteLockedByCurrentThread()) {
            if (LatchSupport.CAPTURE_OWNER) {
                lastOwnerInfo = null;
            }
            if (LatchSupport.TRACK_LATCHES) {
                LatchSupport.trackRelease(this, context);
            }
            writeLock().unlock();
            return;
        }
        if (!ifOwner) {
            throw unexpectedState(
                context.getEnvImplForFatalException(),
                "Latch not held: " + debugString());
        }
    }

    @Override
    public Thread getExclusiveOwner() {
        return getOwner();
    }

    @Override
    public boolean isExclusiveOwner() {
        return isWriteLockedByCurrentThread();
    }

    @Override
    public boolean isOwner() {
        return isWriteLockedByCurrentThread() || (getReadHoldCount() > 0);
    }

    @Override
    public int getNWaiters() {
        return getQueueLength();
    }

    @Override
    public StatGroup getStats() {
        throw unexpectedState();
    }

    @Override
    public void clearStats() {
        throw unexpectedState();
    }

    @Override
    public String toString() {
        return LatchSupport.toString(this, context, lastOwnerInfo);
    }

    @Override
    public String debugString() {
        return LatchSupport.debugString(this, context, lastOwnerInfo);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy