/******************************************************************************* * Copyright (c) 2010 Red Hat, Inc. * Distributed under license by Red Hat, Inc. All rights reserved. * This program is 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: * Red Hat, Inc. - initial API and implementation ******************************************************************************/ package org.jboss.tools.common.model.filesystems.impl; import java.util.HashMap; import java.util.Map; import org.jboss.tools.common.model.XModelObject; /** * This factory provides a new ready to be loaded copy of delegated model object in case when * the delegated model object is being loaded by another thread, and there is a danger of deadlock * in waiting for completion of its loading. If the delegate is loaded, factory returns null. * * @author Viacheslav Kabanovich * */ public class ThreadSafeCopyFactory { XModelObject object; Thread loadingThread = Thread.currentThread(); Map<Thread, XModelObject> concurrentlyLoaded = null; public ThreadSafeCopyFactory(XModelObject object) { this.object = object; } /** * Returns ready to be loaded copy of model object if and only if * this object is being loaded by another thread. * Otherwise, returns null. * * @return */ XModelObject getThreadSafeCopy() { if(loadingThread == null) { concurrentlyLoaded = null; return null; } if(Thread.currentThread() == loadingThread) { return null; } Map<Thread, XModelObject> map = concurrentlyLoaded; XModelObject copy = null; if(map != null) { copy = map.get(Thread.currentThread()); if(copy != null) return copy; } if(object.getParent() instanceof JarFolderImpl) { copy = ((JarFolderImpl)object.getParent()).createValidChildCopy(object); } else if(object.getParent() instanceof FolderImpl) { copy = ((FolderImpl)object.getParent()).createValidChildCopy(object); } if(copy != null) { //Let us wait a bit for this object, maybe there is no lock. for (int i = 0; i < 5; i++) { if(loadingThread != null && !loadingThread.isAlive()) { loadingThread = null; } Thread t = loadingThread; if (t != null) try { t.join(100); } catch (InterruptedException e) { //ignore } if(loadingThread == null) { return null; } } if(map == null) { if(concurrentlyLoaded != null) { map = concurrentlyLoaded; } else { map = new HashMap<Thread, XModelObject>(); concurrentlyLoaded = map; } } map.put(Thread.currentThread(), (AbstractExtendedXMLFileImpl)copy); } return copy; } public void destroy() { loadingThread = null; concurrentlyLoaded = null; } }