From f85ec54f1ceae82880766a9857175376cfbf2b39 Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Wed, 27 Jan 2010 14:42:24 +0000 Subject: [PATCH] Bug 300962: Postpone indexer setup until refresh is done. --- .../cdt/internal/core/pdom/PDOMManager.java | 5 + .../core/pdom/WaitForRefreshJobs.java | 103 ++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/WaitForRefreshJobs.java diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java index 4d780e37b11..4b72e04252c 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java @@ -188,9 +188,11 @@ public class PDOMManager implements IWritableIndexManager, IListener { private ArrayList fSetupParticipants= new ArrayList(); private HashSet fPostponedProjects= new HashSet(); private int fLastNotifiedState= IndexerStateEvent.STATE_IDLE; + private boolean fInShutDown; public PDOMManager() { PDOM.sDEBUG_LOCKS= "true".equals(Platform.getDebugOption(CCorePlugin.PLUGIN_ID + "/debug/index/locks")); //$NON-NLS-1$//$NON-NLS-2$ + addIndexerSetupParticipant(new WaitForRefreshJobs()); fProjectDescriptionListener= new CProjectDescriptionListener(this); fJobChangeListener= new JobChangeListener(this); fPreferenceChangeListener= new IPreferenceChangeListener() { @@ -247,6 +249,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { } public void shutdown() { + fInShutDown= true; new InstanceScope().getNode(CCorePlugin.PLUGIN_ID).removePreferenceChangeListener(fPreferenceChangeListener); CCorePlugin.getDefault().getProjectDescriptionManager().removeCProjectDescriptionListener(fProjectDescriptionListener); final CoreModel model = CoreModel.getDefault(); @@ -1400,6 +1403,8 @@ public class PDOMManager implements IWritableIndexManager, IListener { * @param project */ public void notifyIndexerSetup(IndexerSetupParticipant participant, ICProject project) { + if (fInShutDown) + return; synchronized(fSetupParticipants) { if (fPostponedProjects.contains(project)) { addProject(project); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/WaitForRefreshJobs.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/WaitForRefreshJobs.java new file mode 100644 index 00000000000..afe40b42b9b --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/WaitForRefreshJobs.java @@ -0,0 +1,103 @@ +/******************************************************************************* + * Copyright (c) 2010 Wind River Systems, Inc. and others. + * 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: + * Markus Schorn - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.pdom; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.cdt.core.index.IndexerSetupParticipant; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.jobs.IJobChangeEvent; +import org.eclipse.core.runtime.jobs.IJobChangeListener; +import org.eclipse.core.runtime.jobs.IJobManager; +import org.eclipse.core.runtime.jobs.Job; + +/** + * Postpones indexer setup until there are no running refresh jobs. + */ +public class WaitForRefreshJobs extends IndexerSetupParticipant { + private Set fProjects= new HashSet(); + private Set fRefreshJobs= Collections.synchronizedSet(new HashSet()); + + private IJobChangeListener fJobListener= new IJobChangeListener() { + public void sleeping(IJobChangeEvent event) {} + public void scheduled(IJobChangeEvent event) {} + public void running(IJobChangeEvent event) {} + public void done(IJobChangeEvent event) { + onJobDone(event.getJob()); + } + public void awake(IJobChangeEvent event) {} + public void aboutToRun(IJobChangeEvent event) {} + }; + + @Override + public boolean postponeIndexerSetup(ICProject project) { + // Protect set of projects + synchronized(this) { + if (isRefreshing()) { + fProjects.add(project); + return true; + } + } + return false; + } + + protected void onJobDone(Job job) { + fRefreshJobs.remove(job); + if (fRefreshJobs.isEmpty()) { + checkNotifyIndexer(); + } + } + + private void checkNotifyIndexer() { + Set projects; + // Protect set of projects + synchronized(this) { + if (isRefreshing()) + return; + projects= fProjects; + fProjects= new HashSet(); + } + + for (ICProject project : projects) { + notifyIndexerSetup(project); + } + } + + private boolean isRefreshing() { + updateRefreshJobs(ResourcesPlugin.FAMILY_AUTO_REFRESH); + if (fRefreshJobs.size() != 0) { + return true; + } + + updateRefreshJobs(ResourcesPlugin.FAMILY_MANUAL_REFRESH); + if (fRefreshJobs.size() != 0) { + return true; + } + + return false; + } + + private void updateRefreshJobs(Object jobFamily) { + IJobManager jobManager = Job.getJobManager(); + + Job[] refreshJobs = jobManager.find(jobFamily); + if (refreshJobs != null) { + for (Job j : refreshJobs) { + if (fRefreshJobs.add(j)) { + j.addJobChangeListener(fJobListener); + } + } + } + } +}