Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

close jobs properly, synchronize rule

  • Loading branch information...
commit be8f7f7b73d37d0a2e7b3e048be2858dfaec7497 1 parent 735c85a
@JPMoresmau authored
View
2  net.sf.eclipsefp.haskell-feature/feature.xml
@@ -137,7 +137,7 @@ available at http://www.eclipse.org/legal/epl-v10.html.
id="net.sf.eclipsefp.haskell.util"
download-size="0"
install-size="0"
- version="2.3.1"
+ version="2.3.2"
unpack="false"/>
<plugin
View
2  net.sf.eclipsefp.haskell.browser/META-INF/MANIFEST.MF
@@ -8,7 +8,7 @@ Bundle-Activator: net.sf.eclipsefp.haskell.browser.BrowserPlugin
Require-Bundle: org.eclipse.ui;bundle-version="3.2.0",
org.eclipse.core.runtime;bundle-version="3.2.0",
net.sf.eclipsefp.haskell.core;bundle-version="2.3.2",
- net.sf.eclipsefp.haskell.util;bundle-version="2.3.1",
+ net.sf.eclipsefp.haskell.util;bundle-version="2.3.2",
org.eclipse.jface.text;bundle-version="3.2.0"
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
View
2  net.sf.eclipsefp.haskell.buildwrapper/META-INF/MANIFEST.MF
@@ -8,7 +8,7 @@ Bundle-Vendor: %bundleVendor
Bundle-Localization: plugin
Require-Bundle: org.eclipse.ui,
org.eclipse.core.runtime,
- net.sf.eclipsefp.haskell.util;bundle-version="2.3.1";visibility:=reexport,
+ net.sf.eclipsefp.haskell.util;bundle-version="2.3.2";visibility:=reexport,
org.eclipse.core.resources;bundle-version="3.5.2",
org.eclipse.ui.ide;bundle-version="3.5.2",
org.eclipse.jface.text;bundle-version="3.5.2",
View
40 ...sf.eclipsefp.haskell.buildwrapper/src/net/sf/eclipsefp/haskell/buildwrapper/BWFacade.java
@@ -32,6 +32,7 @@
import net.sf.eclipsefp.haskell.buildwrapper.types.OutlineResult;
import net.sf.eclipsefp.haskell.buildwrapper.types.ThingAtPoint;
import net.sf.eclipsefp.haskell.buildwrapper.types.TokenDef;
+import net.sf.eclipsefp.haskell.buildwrapper.usage.UsageAPI;
import net.sf.eclipsefp.haskell.buildwrapper.util.BWText;
import net.sf.eclipsefp.haskell.util.FileUtil;
import net.sf.eclipsefp.haskell.util.LangUtil;
@@ -86,6 +87,11 @@
* where ever we come from, we only launch one build operation at a time, and lose the intermediate operations
*/
private SingleJobQueue buildJobQueue=new SingleJobQueue();
+
+ /**
+ * where ever we come from, we only launch one synchronize operation at a time, and lose the intermediate operations
+ */
+ private SingleJobQueue synchronizeJobQueue=new SingleJobQueue();
/**
* where ever we come from, we only launch one synchronize operation per file at a time, and lose the intermediate operations
@@ -120,6 +126,13 @@ public SingleJobQueue getBuildJobQueue() {
return buildJobQueue;
}
+ /**
+ * @return the synchronizeJobQueue
+ */
+ public SingleJobQueue getSynchronizeJobQueue() {
+ return synchronizeJobQueue;
+ }
+
public synchronized SingleJobQueue getThingAtPointJobQueue(IFile f){
SingleJobQueue sjq=tapQueuesByFiles.get(f);
if (sjq==null){
@@ -129,6 +142,10 @@ public synchronized SingleJobQueue getThingAtPointJobQueue(IFile f){
return sjq;
}
+ public synchronized Collection<SingleJobQueue> getThingAtPointJobQueues(){
+ return tapQueuesByFiles.values();
+ }
+
/**
* do we have a editor synchronize queue (ie have we synchronized with the editor during that session already)
* @param f
@@ -148,6 +165,11 @@ public synchronized SingleJobQueue getEditorSynchronizeQueue(IFile f){
return sjq;
}
+ public synchronized Collection<SingleJobQueue> getEditorSynchronizeJobQueues(){
+ return syncEditorJobQueue.values();
+ }
+
+
private void deleteCabalProblems(){
String relCabal=getCabalFile().substring(getProject().getLocation().toOSString().length());
IFile f=getProject().getFile(relCabal);
@@ -377,12 +399,18 @@ public void generateUsage(Component c,boolean returnAll){
}
}
}
- for (int a=0;a<allPaths.length();a++){
- try {
- String p=allPaths.getString(a);
- BuildWrapperPlugin.getDefault().getUsageAPI().addFile(getProject(),c, p);
- } catch (JSONException je){
- BuildWrapperPlugin.logError(BWText.error_parsing_usage_path, je);
+ BuildWrapperPlugin plugin=BuildWrapperPlugin.getDefault();
+ if (plugin!=null){
+ for (int a=0;a<allPaths.length();a++){
+ try {
+ String p=allPaths.getString(a);
+ UsageAPI api=plugin.getUsageAPI();
+ if (api!=null){
+ api.addFile(getProject(),c, p);
+ }
+ } catch (JSONException je){
+ BuildWrapperPlugin.logError(BWText.error_parsing_usage_path, je);
+ }
}
}
}
View
13 ...fp.haskell.buildwrapper/src/net/sf/eclipsefp/haskell/buildwrapper/BuildWrapperPlugin.java
@@ -9,6 +9,7 @@
import net.sf.eclipsefp.haskell.buildwrapper.usage.UsageThread;
import net.sf.eclipsefp.haskell.buildwrapper.util.BWText;
import net.sf.eclipsefp.haskell.util.FileUtil;
+import net.sf.eclipsefp.haskell.util.SingleJobQueue;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
@@ -74,6 +75,18 @@ public void start(BundleContext context) throws Exception {
*/
public void stop(BundleContext context) throws Exception {
plugin = null;
+
+ for (BWFacade f:facades.values()){
+ f.getBuildJobQueue().close();
+ f.getSynchronizeJobQueue().close();
+ for (SingleJobQueue q:f.getThingAtPointJobQueues()){
+ q.close();
+ }
+ for (SingleJobQueue q:f.getEditorSynchronizeJobQueues()){
+ q.close();
+ }
+ }
+
usageThread.setShouldStop();
// wait for all pending writes for 10 secs
usageThread.join(10000);
View
30 ...f.eclipsefp.haskell.buildwrapper/src/net/sf/eclipsefp/haskell/buildwrapper/JobFacade.java
@@ -28,6 +28,7 @@
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.jface.text.IDocument;
@@ -128,6 +129,22 @@ public void done(IJobChangeEvent event) {
sj.schedule();
}
+ /**
+ * a simple rule only conflicting with itself
+ */
+ private static final ISchedulingRule synchronizeRule=new ISchedulingRule() {
+
+ @Override
+ public boolean isConflicting(ISchedulingRule arg0) {
+ return this==arg0;
+ }
+
+ @Override
+ public boolean contains(ISchedulingRule arg0) {
+ return this==arg0;
+ }
+ };
+
private Job getSynchronizeJob(final boolean force) {
final String jobNamePrefix = NLS.bind(BWText.job_synchronize, getProject().getName());
@@ -144,8 +161,11 @@ protected IStatus run(IProgressMonitor monitor) {
}
};
- //
- buildJob.setRule( getProject().getWorkspace().getRoot() );
+ // why?
+ // build is a project only rule, but synchronize is hard on the disk, so we only want one synchronize at the same time
+ // but we don't want buildJob.setRule( getProject().getWorkspace().getRoot() ); because then any other operation will wait for synchronize
+ // so we only disallow concurrent synchronize, but don't influence with the rest (other operations)
+ buildJob.setRule(synchronizeRule);
buildJob.setPriority(Job.BUILD);
buildJob.addJobChangeListener(new JobChangeAdapter(){
/* (non-Javadoc)
@@ -165,7 +185,7 @@ public void done(IJobChangeEvent event) {
}
public void synchronize(final boolean force) {
- getSynchronizeJob(force).schedule();
+ realFacade.getSynchronizeJobQueue().addJob(getSynchronizeJob(force));
}
public void outline(final IFile f,final OutlineHandler handler){
@@ -177,7 +197,9 @@ protected IStatus run(IProgressMonitor monitor) {
try {
monitor.beginTask(jobNamePrefix, IProgressMonitor.UNKNOWN);
OutlineResult or=realFacade.outline(f);
- handler.handleOutline(or);
+ if(!monitor.isCanceled()){
+ handler.handleOutline(or);
+ }
} finally {
monitor.done();
}
View
2  net.sf.eclipsefp.haskell.core/META-INF/MANIFEST.MF
@@ -10,7 +10,7 @@ Require-Bundle: org.eclipse.core.expressions;bundle-version="[3.2.0,4.0.0)",
org.eclipse.debug.core;bundle-version="[3.2.0,4.0.0)",
org.eclipse.ui;bundle-version="3.5.0",
org.eclipse.text;bundle-version="3.5.0",
- net.sf.eclipsefp.haskell.util;bundle-version="2.3.1",
+ net.sf.eclipsefp.haskell.util;bundle-version="2.3.2",
net.sf.eclipsefp.haskell.hlint;bundle-version="2.3.1",
org.eclipse.ui.editors;bundle-version="3.5.0",
org.eclipse.ui.ide;bundle-version="3.5.2",
View
2  net.sf.eclipsefp.haskell.util/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %bundleName
Bundle-SymbolicName: net.sf.eclipsefp.haskell.util
-Bundle-Version: 2.3.1
+Bundle-Version: 2.3.2
Bundle-Activator: net.sf.eclipsefp.haskell.util.Activator
Require-Bundle: org.eclipse.core.runtime,
org.eclipse.core.resources,
View
153 net.sf.eclipsefp.haskell.util/src/net/sf/eclipsefp/haskell/util/SingleJobQueue.java
@@ -1,70 +1,83 @@
-package net.sf.eclipsefp.haskell.util;
-
-import org.eclipse.core.runtime.jobs.IJobChangeEvent;
-import org.eclipse.core.runtime.jobs.Job;
-import org.eclipse.core.runtime.jobs.JobChangeAdapter;
-
-/**
- * ensure that only one job of a given type runs and only one job waits, intermediate jobs are discarded
- * @author JP Moresmau
- *
- */
-public class SingleJobQueue {
- /**
- * lock to ensure concurrency
- */
- private Object lock=new Object();
-
- /**
- * the currently running job
- */
- private Job current;
- /**
- * the next job to run
- */
- private Job next;
-
- /**
- * add a job to the queue
- * if the queue is empty, schedule the job straight away
- * otherwise queue the job (losing the previously waiting job if any)
- * @param j
- */
- public void addJob(Job j){
- synchronized (lock){
- if (current==null){
- current=j;
- launchCurrent();
- } else {
- next=j;
- }
- }
- }
-
- /**
- * launch the current job with a listener that will launch the waiting job on completion
- */
- private void launchCurrent(){
- if (current!=null){
- current.addJobChangeListener(new ScheduleNextListener());
- current.schedule();
- }
- }
-
- private class ScheduleNextListener extends JobChangeAdapter {
- @Override
- public void done(IJobChangeEvent event) {
- synchronized (lock) {
- // we're not running
- current=null;
- // we have a job waiting, let's run it
- if (next!=null){
- current=next;
- next=null;
- launchCurrent();
- }
- }
- }
- }
-
-}
+package net.sf.eclipsefp.haskell.util;
+
+import org.eclipse.core.runtime.jobs.IJobChangeEvent;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.core.runtime.jobs.JobChangeAdapter;
+
+/**
+ * ensure that only one job of a given type runs and only one job waits, intermediate jobs are discarded
+ * @author JP Moresmau
+ *
+ */
+public class SingleJobQueue {
+ /**
+ * lock to ensure concurrency
+ */
+ private Object lock=new Object();
+
+ /**
+ * the currently running job
+ */
+ private Job current;
+ /**
+ * the next job to run
+ */
+ private Job next;
+
+ /**
+ * add a job to the queue
+ * if the queue is empty, schedule the job straight away
+ * otherwise queue the job (losing the previously waiting job if any)
+ * @param j
+ */
+ public void addJob(Job j){
+ synchronized (lock){
+ if (current==null){
+ current=j;
+ launchCurrent();
+ } else {
+ next=j;
+ }
+ }
+ }
+
+ /**
+ * close the queue: cancel current job and remove next
+ */
+ public void close(){
+ synchronized (lock){
+ next=null;
+ if (current!=null){
+ current.cancel();
+ }
+ current=null;
+ }
+ }
+
+ /**
+ * launch the current job with a listener that will launch the waiting job on completion
+ */
+ private void launchCurrent(){
+ if (current!=null){
+ current.addJobChangeListener(new ScheduleNextListener());
+ current.schedule();
+ }
+ }
+
+ private class ScheduleNextListener extends JobChangeAdapter {
+ @Override
+ public void done(IJobChangeEvent event) {
+ synchronized (lock) {
+ // we're not running
+ current=null;
+ // we have a job waiting, let's run it
+ if (next!=null){
+ current=next;
+ next=null;
+ launchCurrent();
+ }
+ }
+ }
+ }
+
+}
View
4 todo.txt
@@ -14,6 +14,10 @@
- code navigation like chris done? http://dl.dropbox.com/u/62227452/Screenshots/code-navigationz-moving.ogv
keep locations from ast?
Does Eclipse provide easy way to do that in the editor?
+ Yes, Eclipse does it for Java: http://help.eclipse.org/juno/index.jsp?topic=%2Forg.eclipse.jdt.doc.user%2Freference%2Fref-menu-edit.htm
+ So we need to:
+ - have buildwrapper build1 return the locations from the AST
+ - implement the navigation ourselves in the AST location tree
- latest version of haskell-src-exts exposes lexer, would that be better to use than GHC lexer?
Please sign in to comment.
Something went wrong with that request. Please try again.