class AbstractTSQueueLock extends AbstractCloseable implements Closeable {
    protected static final String UNLOCK_MAIN_MSG = ". You can manually unlock with net.openhft.chronicle.queue.main.UnlockMain";
    protected static final String UNLOCKING_FORCIBLY_MSG = ". Unlocking forcibly. Note that this feature is designed to recover " +
            "if another process died while holding a lock. If the other process is still alive, you may see queue corruption.";
    protected static final long PID = getProcessId();
    public static final long UNLOCKED = 1L << 63;
    protected final UnlockMode forceUnlockOnTimeoutWhen;

    protected final LongValue lock;
    protected final ThreadLocal<TimingPauser> pauser;
    protected final File path;
    protected final TableStore tableStore;
    private final String lockKey;

    public AbstractTSQueueLock(final String lockKey, final TableStore<?> tableStore, final Supplier<TimingPauser> pauserSupplier) {
        this.tableStore = tableStore;
        this.lock = tableStore.doWithExclusiveLock(ts -> ts.acquireValueFor(lockKey));
        this.pauser = ThreadLocal.withInitial(pauserSupplier);
        this.path = tableStore.file();
        this.lockKey = lockKey;

        final boolean dontRecoverLockTimeout = Jvm.getBoolean("queue.dont.recover.lock.timeout");
        if (dontRecoverLockTimeout) {
            forceUnlockOnTimeoutWhen = UnlockMode.NEVER;
            Jvm.warn().on(getClass(), "queue.dont.recover.lock.timeout property is deprecated and will be removed in a future version. " +
                    "Use queue.force.unlock.mode=NEVER instead");
        } else {
            forceUnlockOnTimeoutWhen = UnlockMode.valueOf(Jvm.getProperty("queue.force.unlock.mode", UnlockMode.LOCKING_PROCESS_DEAD.name()).toUpperCase());
        }

        singleThreadedCheckDisabled(true);
    }

    protected void performClose() {
        Closeable.closeQuietly(lock);
    }

    /**
     * will only force unlock if you give it the correct pid
     */
    protected void forceUnlock(long value) {
        boolean unlocked = lock.compareAndSwapValue(value, UNLOCKED);
        Jvm.warn().on(getClass(), "" +
                        "Forced unlock for the " +
                        "lock file:" + path + ", " +
                        "lockKey: " + lockKey + ", " +
                        "unlocked: " + unlocked,
                new StackTrace("Forced unlock"));
    }

    public boolean isLockedByCurrentProcess(LongConsumer notCurrentProcessConsumer) {
        final long pid = this.lock.getVolatileValue();
        // mask off thread (if used)
        int realPid = (int) pid;
        if (realPid == PID)
            return true;
        notCurrentProcessConsumer.accept(pid);
        return false;
    }

    /**
     * forces an unlock only if the process that currently holds the table store lock is no-longer running
     *
     * @return {@code true} if the lock was already unlocked, It will not release the lock if it is held by this process
     * or the process that was holding the lock is no longer running (and we were able to unlock).
     * Otherwise {@code false} is returned if the lock is held by this process or another live process.
     */
    public boolean forceUnlockIfProcessIsDead() {<FILL_FUNCTION_BODY>}

    /**
     * @return the pid that had the locked or the returns UNLOCKED if it is not locked
     */
    public long lockedBy() {
        return lock.getVolatileValue();
    }

    @Override
    public String toString() {
        return this.getClass().getSimpleName() + "{" +
                "lock=" + lock +
                ", path=" + path +
                ", lockKey='" + lockKey + '\'' +
                '}';
    }
}

        long pid;
        for (; ; ) {
            pid = this.lock.getVolatileValue();
            if (pid == UNLOCKED)
                return true;

            // mask off thread (if used)
            int realPid = (int) pid;
            if (!Jvm.isProcessAlive(realPid)) {
                Jvm.warn().on(this.getClass(), format("Forced unlocking `%s` in lock file:%s, as this was locked by: %d which is now dead",
                        lockKey, this.path, realPid));
                if (lock.compareAndSwapValue(pid, UNLOCKED))
                    return true;
            } else
                break;
        }
        if (Jvm.isDebugEnabled(this.getClass()))
            // don't make this a WARN as this method should only unlock if process is dead or current process.
            Jvm.debug().on(this.getClass(), format("Unable to release the lock=%s in the table store file=%s " +
                    "as it is being held by pid=%d, and this process is still running.", lockKey, path, pid));
        return false;
    
<methods>public static void assertCloseablesClosed() ,public final void close() ,public net.openhft.chronicle.core.StackTrace createdHere() ,public static void disableCloseableTracing() ,public static void enableCloseableTracing() ,public static void gcAndWaitForCloseablesToClose() ,public boolean isClosed() ,public boolean isClosing() ,public int referenceId() ,public void singleThreadedCheckDisabled(boolean) ,public void singleThreadedCheckReset() ,public void throwExceptionIfClosed() throws net.openhft.chronicle.core.io.ClosedIllegalStateException, net.openhft.chronicle.core.io.ThreadingIllegalStateException,public void throwExceptionIfClosedInSetter() throws net.openhft.chronicle.core.io.ClosedIllegalStateException, net.openhft.chronicle.core.io.ThreadingIllegalStateException,public java.lang.String toString() ,public static void unmonitor(net.openhft.chronicle.core.io.Closeable) ,public static boolean waitForCloseablesToClose(long) ,public void warnAndCloseIfNotClosed() <variables>private static final long CLOSED_OFFSET,protected static final boolean DISABLE_DISCARD_WARNING,private static final int STATE_CLOSED,private static final int STATE_CLOSING,private static final int STATE_NOT_CLOSED,protected static final long WARN_NS,private volatile transient int closed,protected volatile transient net.openhft.chronicle.core.StackTrace closedHere,private final transient net.openhft.chronicle.core.StackTrace createdHere,private final transient net.openhft.chronicle.core.io.AbstractCloseable.Finalizer finalizer,private int referenceId,private transient boolean singleThreadedCheckDisabled,private volatile transient java.lang.Thread usedByThread,private volatile transient net.openhft.chronicle.core.StackTrace usedByThreadHere