/* * eXist Open Source Native XML Database * Copyright (C) 2007 The eXist Project * http://exist-db.org * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * $Id$ */ package org.exist.storage.lock; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Condition; import org.apache.log4j.Logger; import org.exist.util.LockException; import org.exist.util.DeadlockException; /** * Wraps around a thread in order to be able to suspend it completely while it is waiting * for a lock. */ public class WaitingThread implements LockListener { private final static Logger LOG = Logger.getLogger(WaitingThread.class); private Condition monitor; private MultiReadReentrantLock lock; private int lockType; private Thread thread; private boolean suspended = false; private boolean deadlocked = false; public WaitingThread(Thread thread, Condition monitor, MultiReadReentrantLock lock, int lockType) { this.monitor = monitor; this.lock = lock; this.thread = thread; this.lockType = lockType; } /** * Start waiting on the monitor object. Continue waiting if the thread wakes up * and suspended is set to true. Only stop waiting if suspended is false. * * @throws LockException */ public void doWait() throws LockException { do { try { monitor.await(500, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { throw new LockException("Interrupted while waiting for read lock"); } if (deadlocked) { LOG.warn("Deadlock detected: cancelling wait..."); throw new DeadlockException(); } } while (suspended); } public void signalDeadlock() { deadlocked = true; monitor.signal(); } /** * Put the thread into suspended mode, i.e. keep it asleep even if * a notify causes it to wake up temporarily. */ public void suspendWaiting() { suspended = true; } /** * Wake the thread from suspended mode. */ public void lockReleased() { // LOG.debug("Reactivate suspended lock: " + thread.getName()); suspended = false; monitor.signal(); } public boolean isSuspended() { return suspended; } public Thread getThread() { return thread; } public Lock getLock() { return lock; } public int getLockType() { return lockType; } public boolean equals(Object obj) { return thread == ((WaitingThread)obj).getThread(); } }