|
What this is
Other links
The source code/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is NetBeans. The Initial Developer of the Original * Code is Sun Microsystems, Inc. Portions Copyright 1997-2004 Sun * Microsystems, Inc. All Rights Reserved. */ package org.netbeans.modules.javacore; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import org.netbeans.jmi.javamodel.Element; import org.netbeans.mdr.util.TransactionMutex; import org.netbeans.modules.javacore.api.JavaModel; import org.netbeans.modules.javacore.jmiimpl.javamodel.ResourceImpl; import org.netbeans.modules.javacore.jmiimpl.javamodel.SemiPersistentElement; import org.openide.ErrorManager; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.netbeans.modules.javacore.jmiimpl.javamodel.BehavioralFeatureImpl; import org.netbeans.modules.javacore.jmiimpl.javamodel.EnumConstantImpl; import org.netbeans.modules.javacore.jmiimpl.javamodel.FeatureImpl; import org.netbeans.modules.javacore.jmiimpl.javamodel.FieldImpl; import org.netbeans.modules.javacore.internalapi.ExternalChange; import org.netbeans.modules.javacore.internalapi.JavaMetamodel; import org.netbeans.modules.javacore.classpath.FilterClassPathImplementation; import org.netbeans.api.java.classpath.ClassPath; import org.openide.filesystems.FileObject; import org.openide.loaders.DataObject; import javax.swing.SwingUtilities; /** * * @author Martin Matula */ public class ExclusiveMutex extends TransactionMutex { private static final boolean DEBUG = false; private boolean changes = false; private boolean fail = false; private Thread thread = null; private int counter = 0; private Set newObjects = new HashSet(); // set of changed resources private Set changedRscSet = new HashSet(); private Set changedExternalSet = new HashSet(); private Set upToDateElements = new HashSet(); private Set invalidClasses = new HashSet(); // list of BehavioralElements, which has to be reinitialized after commit private List initBodyQueue; // cache used by MDRParser for scopes private Map parserCache; private Set needParsing = new HashSet(); private Set needParsingRW = new HashSet(); private Set needTSUpdate = new HashSet(); private Set priorityThreads = null; private ClassPath classPath = null; private volatile boolean isSwingWaiting = false; private JMManager manager = (JMManager) JMManager.getManager(); /** Creates a new instance of ExclusiveMutex */ public ExclusiveMutex(Object p1, Object p2, Object p3) { super(p1, p2, p3); } // can be called only from within a transaction public boolean isSwingWaiting() { return isSwingWaiting; } public synchronized void addPriorityThread() { if (priorityThreads == null) { priorityThreads = new HashSet(); } priorityThreads.add(Thread.currentThread()); } public synchronized void enter(boolean writeAccess) { Thread thread = Thread.currentThread(); if (SwingUtilities.isEventDispatchThread()) addPriorityThread(); boolean isPriorityThread = priorityThreads != null && priorityThreads.remove(thread); while (!(this.thread == thread || (counter == 0 && (!isSwingWaiting || isPriorityThread)))) { try { isSwingWaiting |= isPriorityThread; // if (isPriorityThread) { // System.err.println("Priority thread waiting: " + thread.toString()); // Thread.dumpStack(); // } this.wait(); } catch (InterruptedException e) { ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e); } } // if (writeAccess && endTransInProgress) { // throw new IllegalStateException("Cannot do modifications while commit/rollback in progress."); // } this.thread = thread; counter++; if (JMManager.TRANS_DEBUG && counter == 1) { Thread.dumpStack(); } if (isPriorityThread) { // System.out.print("."); if (priorityThreads != null && priorityThreads.isEmpty()) { priorityThreads = null; } isSwingWaiting = priorityThreads != null; } if (writeAccess) { if (!changes) { changes = true; start(); } } boolean success = false; try { parseIfNeeded(writeAccess && counter == 1); success = true; } finally { if (!success) { try { if (changes && counter == 1) { end(true); notifyElements(); ClassIndex.rollback(); } } catch (RuntimeException x) { // throw the original exception rather than x ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, x); } finally { counter--; if (counter == 0) { thread = null; this.fail = false; changes = false; this.notifyAll(); } } } } if (counter == 1) clearClassPath(); } private void clearClassPath() { classPath = null; } private void clearParserCache() { parserCache=null; } private void parseIfNeeded(boolean writeAccess) { boolean isEmpty; DataObject[] jdos; synchronized (needParsingRW) { isEmpty = needParsingRW.isEmpty(); } if (!isEmpty) { synchronized (needParsingRW) { jdos = (DataObject[]) needParsingRW.toArray(new DataObject[needParsingRW.size()]); needParsingRW.clear(); } for (int i = 0; i < jdos.length; i++) { DataObject dobj=jdos[i]; if (!dobj.isValid()) continue; JavaModel.setClassPath(dobj.getPrimaryFile()); RepositoryUpdater.createOrUpdateResource(dobj); } } if (writeAccess) { synchronized (needParsing) { isEmpty = needParsing.isEmpty(); } if (!isEmpty) { synchronized (needParsing) { jdos = (DataObject[]) needParsing.toArray(new DataObject[needParsing.size()]); if (DEBUG) { System.err.println("cleaning needParsing"); // NOI18N Thread.dumpStack(); } needParsing.clear(); } for (int i = 0; i < jdos.length; i++) { DataObject dobj=jdos[i]; FileObject fobj; ResourceImpl res; if (!dobj.isValid()) continue; fobj=dobj.getPrimaryFile(); JavaModel.setClassPath(fobj); res = (ResourceImpl) JavaMetamodel.getManager().getResource(fobj); if (res != null) { res.updateFromDataObject(dobj,true); } } } } synchronized (needTSUpdate) { isEmpty = needTSUpdate.isEmpty(); } if (!isEmpty) { FileObject[] fos; synchronized (needTSUpdate) { fos = (FileObject[]) needTSUpdate.toArray(new FileObject[needTSUpdate.size()]); needTSUpdate.clear(); } for (int i = 0; i < fos.length; i++) { FileObject fo = fos[i]; if (!fo.isValid()) continue; RepositoryUpdater.updateTimeStamp(fo); } } } public Thread getThread() { return thread; } public void addModified(DataObject jdo) { if (DEBUG) { System.out.println("adding " + jdo + " to needParsing"); // NOI18N Thread.dumpStack(); } needParsing.add(jdo); } public boolean removeModified(DataObject jdo) { if (DEBUG) { System.out.println("removing " + jdo + " from needParsing"); // NOI18N Thread.dumpStack(); } return needParsing.remove(jdo); } void addModifiedRW(DataObject jdo) { synchronized (needParsingRW) { synchronized (needParsing) { needParsingRW.add(jdo); needParsing.remove(jdo); } } } void addUpdateTS(FileObject fo) { synchronized (needTSUpdate) { needTSUpdate.add(fo); } } public synchronized boolean leave(boolean fail) { assert thread == Thread.currentThread() : "Cannot end transaction from a different thread!"; if (fail) { JMManager.getLog().notify(ErrorManager.INFORMATIONAL,new Exception("rollback!!!")); // NOI18N } boolean result = false; try { if (changes) { this.fail |= fail; } else { if (fail) throw new RuntimeException("Cannot fail in read mode."); // NOI18N } if (counter == 1) { result = true; if (changes) { // endTransInProgress = true; if (this.fail) { end(true); notifyElements(); ClassIndex.rollback(); } else { notifyElements(); end(false); ClassIndex.commit(); } } } } catch (RuntimeException x) { ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, x); this.fail = true; try { end(true); } catch (RuntimeException e) { ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e); } try { notifyElements(); } catch (RuntimeException e) { ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e); } try { ClassIndex.rollback(); } catch (RuntimeException e) { ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e); } } finally { if (counter > 0) { if ((--counter) == 0) { try { // endTransInProgress = false; thread = null; this.fail = false; if (changes) { //needParsing.clear(); changes = false; } clearClassPath(); clearParserCache(); } finally { this.notifyAll(); } } } else { throw new RuntimeException("Error: leave() without enter()."); // NOI18N } } return result; } void setClassPath(List/* |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.