/*=============================================================================#
# Copyright (c) 2015-2016 Stephan Wahlbrink (WalWare.de) 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:
# Stephan Wahlbrink - initial API and implementation
#=============================================================================*/
package de.walware.docmlet.base.ui.processing;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
public abstract class DocProcessingToolOperationContext {
private static final byte S_CANCELED= 0b0_0000_0001;
private static final byte S_START= 0b0_0001_0000;
private static final byte S_PROCESSING= 0b0_0010_0000;
private static final byte S_FINISHED= 0b0_0111_0000;
private volatile byte state;
private Runnable runnable;
private Exception error;
public DocProcessingToolOperationContext() {
}
public synchronized void start(final DocProcessingToolProcess toolProcess, final Runnable runnable,
final SubMonitor m) throws Exception {
if (toolProcess == null) {
throw new NullPointerException("tool"); //$NON-NLS-1$
}
if (runnable == null) {
throw new NullPointerException("runnable"); //$NON-NLS-1$
}
this.state= S_START;
this.runnable= runnable;
this.error= null;
try {
start(toolProcess, m);
RUN: while (this.state < S_FINISHED) {
try {
switch (this.state) {
case (S_START | S_CANCELED):
canceling(false);
break RUN;
case (S_PROCESSING | S_CANCELED):
canceling(true);
break;
default:
break;
}
notifyAll();
wait(100);
}
catch (final InterruptedException e) {
}
}
if (this.error != null) {
throw this.error;
}
if (isCanceled()) {
throw new CoreException(Status.CANCEL_STATUS);
}
}
finally {
this.runnable= null;
this.error= null;
}
}
public final synchronized void cancel() {
this.state|= S_CANCELED;
notifyAll();
}
public boolean isCanceled() {
return ((this.state & S_CANCELED) != 0);
}
public abstract String getId();
public abstract String getLabel();
protected abstract void start(DocProcessingToolProcess toolProcess,
SubMonitor m) throws CoreException;
protected void canceling(final boolean running) {
}
protected void runInContext() {
final Runnable runnable;
synchronized (this) {
if (this.state != S_START) {
return;
}
this.state= S_PROCESSING;
runnable= this.runnable;
}
try {
runnable.run();
}
catch (final Exception e) {
this.error= e;
}
finally {
synchronized (this) {
this.state= S_FINISHED;
notifyAll();
}
}
}
}