/*******************************************************************************
* Copyright (c) 2014 Bruno Medeiros and other Contributors.
* 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
*
* Contributors:
* Bruno Medeiros - initial API and implementation
*******************************************************************************/
package melnorme.lang.tooling.engine;
import static melnorme.utilbox.core.Assert.AssertNamespace.assertTrue;
import java.util.HashMap;
public class LoopDetector {
// This map forms a tree, each thread id is a node.
private HashMap<Long, Long> waitingThreads = new HashMap<>();
public synchronized void registerWaitingThread(long currentThreadId, long otherThreadId)
throws ResolutionLoopException {
assertTrue(waitingThreads.containsKey(currentThreadId) == false);
checkForLoop(currentThreadId, otherThreadId);
waitingThreads.put(currentThreadId, otherThreadId);
}
private void checkForLoop(long currentThreadId, long otherThreadId) throws ResolutionLoopException {
if(currentThreadId == otherThreadId) {
throw new ResolutionLoopException();
}
Long nextId = waitingThreads.get(otherThreadId);
if(nextId != null) {
checkForLoop(currentThreadId, nextId);
}
}
public synchronized void unregisterWaitingThread(long currentThreadId) {
assertTrue(waitingThreads.containsKey(currentThreadId));
waitingThreads.remove(currentThreadId);
}
@SuppressWarnings("serial")
public static class ResolutionLoopException extends Throwable {
}
}