[Pydev-cvs] org.python.pydev/src/org/python/pydev/editor PyReconciler.java, 1.2, 1.3
Brought to you by:
fabioz
From: Fabio Z. <fa...@us...> - 2008-07-20 14:14:20
|
Update of /cvsroot/pydev/org.python.pydev/src/org/python/pydev/editor In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv10981/src/org/python/pydev/editor Modified Files: PyReconciler.java Log Message: Fixed on deadlock involving PyReconciler -- spell service (and multiple editors on the same file) Bug: https://sourceforge.net/tracker/index.php?func=detail&aid=2013310&group_id=85796&atid=577329 Index: PyReconciler.java =================================================================== RCS file: /cvsroot/pydev/org.python.pydev/src/org/python/pydev/editor/PyReconciler.java,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** PyReconciler.java 19 Jul 2008 22:50:16 -0000 1.2 --- PyReconciler.java 20 Jul 2008 14:14:28 -0000 1.3 *************** *** 3,6 **** --- 3,7 ---- import java.util.ArrayList; import java.util.HashMap; + import java.util.HashSet; import java.util.Iterator; import java.util.List; *************** *** 85,89 **** List toRemove = new ArrayList(); ! Object fLockObject; if (fAnnotationModel instanceof ISynchronizable){ --- 86,90 ---- List toRemove = new ArrayList(); ! Object fLockObject; if (fAnnotationModel instanceof ISynchronizable){ *************** *** 92,119 **** fLockObject = new Object(); } ! ! synchronized (fLockObject) { ! Iterator iter = fAnnotationModel.getAnnotationIterator(); ! while (iter.hasNext()) { ! Object n = iter.next(); ! if (n instanceof SpellingAnnotation) { ! toRemove.add(n); } } Annotation[] annotationsToRemove = (Annotation[]) toRemove.toArray(new Annotation[toRemove.size()]); ! if (fAnnotationModel instanceof IAnnotationModelExtension) { ! ((IAnnotationModelExtension) fAnnotationModel).replaceAnnotations(annotationsToRemove, fAddAnnotations); ! } else { ! for (int i = 0; i < annotationsToRemove.length; i++) { ! fAnnotationModel.removeAnnotation(annotationsToRemove[i]); ! } ! for (iter = fAddAnnotations.keySet().iterator(); iter.hasNext();) { ! Annotation annotation = (Annotation) iter.next(); ! fAnnotationModel.addAnnotation(annotation, (Position) fAddAnnotations.get(annotation)); } } } - fAddAnnotations = null; } --- 93,141 ---- fLockObject = new Object(); } ! ! //let other threads execute before getting the lock on the annotation model ! Thread.yield(); ! ! Thread thread = Thread.currentThread(); ! int initiaThreadlPriority = thread.getPriority(); ! try{ ! //before getting the lock, let's execute with normal priority, to optimize the time that we'll ! //retain that object locked (the annotation model is used on lots of places, so, retaining the lock ! //on it on a minimum priority thread is not a good thing. ! thread.setPriority(Thread.NORM_PRIORITY); ! Iterator iter; ! ! synchronized (fLockObject) { ! iter = fAnnotationModel.getAnnotationIterator(); ! while (iter.hasNext()) { ! Object n = iter.next(); ! if (n instanceof SpellingAnnotation) { ! toRemove.add(n); ! } } + iter = null; } + Annotation[] annotationsToRemove = (Annotation[]) toRemove.toArray(new Annotation[toRemove.size()]); ! //let other threads execute before getting the lock (again) on the annotation model ! Thread.yield(); ! synchronized (fLockObject) { ! if (fAnnotationModel instanceof IAnnotationModelExtension) { ! ((IAnnotationModelExtension) fAnnotationModel).replaceAnnotations(annotationsToRemove, fAddAnnotations); ! } else { ! for (int i = 0; i < annotationsToRemove.length; i++) { ! fAnnotationModel.removeAnnotation(annotationsToRemove[i]); ! } ! for (iter = fAddAnnotations.keySet().iterator(); iter.hasNext();) { ! Annotation annotation = (Annotation) iter.next(); ! fAnnotationModel.addAnnotation(annotation, (Position) fAddAnnotations.get(annotation)); ! } } } + + }finally{ + thread.setPriority(initiaThreadlPriority); } fAddAnnotations = null; } *************** *** 131,139 **** private SpellingService fSpellingService; - private ISpellingProblemCollector fSpellingProblemCollector; - /** The spelling context containing the Java source content type. */ private SpellingContext fSpellingContext; /** * Creates a new comment reconcile strategy. --- 153,170 ---- private SpellingService fSpellingService; /** The spelling context containing the Java source content type. */ private SpellingContext fSpellingContext; + + /** + * Set containing the models that are being checked at the current moment (this is used + * so that when there are multiple editors binded to the same model, we only make the check in one of those + * models -- the others don't need to do anything, as it's based on the annotation model that's shared + * among them) + * + * It's static so that we can share it among threads. + */ + private static HashSet<IAnnotationModel> modelBeingChecked = new HashSet<IAnnotationModel>(); + /** * Creates a new comment reconcile strategy. *************** *** 150,153 **** --- 181,185 ---- fSpellingContext.setContentType(getContentType()); } + /* *************** *** 176,183 **** */ public void reconcile(IRegion region) { ! if (fViewer.getAnnotationModel() == null || fSpellingProblemCollector == null) { return; } try { //we're not using incremental updates!!! -- that's why the region is ignored and fDocument.len is used. --- 208,227 ---- */ public void reconcile(IRegion region) { ! IAnnotationModel annotationModel = fViewer.getAnnotationModel(); ! ! if (annotationModel == null) { return; } + //Bug: https://sourceforge.net/tracker/index.php?func=detail&aid=2013310&group_id=85796&atid=577329 + //When having multiple editors for the same document, only one of the reconcilers actually needs to + //work (because the others are binded to the same annotation model, so, having one do the work is enough) + synchronized (modelBeingChecked) { + if(modelBeingChecked.contains(annotationModel)){ + return; + } + modelBeingChecked.add(annotationModel); + } + try { //we're not using incremental updates!!! -- that's why the region is ignored and fDocument.len is used. *************** *** 188,193 **** ArrayList<IRegion> regions = new ArrayList<IRegion>(); for (ITypedRegion partition : partitions) { ! if (fProgressMonitor != null && fProgressMonitor.isCanceled()) return; String type = partition.getType(); --- 232,238 ---- ArrayList<IRegion> regions = new ArrayList<IRegion>(); for (ITypedRegion partition : partitions) { ! if (fProgressMonitor != null && fProgressMonitor.isCanceled()){ return; + } String type = partition.getType(); *************** *** 201,205 **** int size = regions.size(); if (size > 0) { ! fSpellingService.check(fDocument, regions.toArray(new IRegion[size]), fSpellingContext, fSpellingProblemCollector, fProgressMonitor); } --- 246,252 ---- int size = regions.size(); if (size > 0) { ! //only create the collector when actually needed for the current model ! ISpellingProblemCollector spellingProblemCollector = new SpellingProblemCollector(annotationModel); ! fSpellingService.check(fDocument, regions.toArray(new IRegion[size]), fSpellingContext, spellingProblemCollector, fProgressMonitor); } *************** *** 207,210 **** --- 254,262 ---- } catch (Exception e) { PydevPlugin.log(e); + + }finally{ + synchronized (modelBeingChecked) { + modelBeingChecked.remove(annotationModel); + } } } *************** *** 226,235 **** fDocument = document; ! IAnnotationModel model = fViewer.getAnnotationModel(); ! if (model == null) { ! fSpellingProblemCollector = null; ! } else { ! fSpellingProblemCollector = new SpellingProblemCollector(model); ! } } --- 278,283 ---- fDocument = document; ! //Note: if we have multiple editors for the same doc, the document and the annotation model will be the same ! //for multiple reconcilers } |