diff --git a/ch.psi.fda/src/main/java/ch/psi/fda/core/actions/ChannelAccessCondition.java b/ch.psi.fda/src/main/java/ch/psi/fda/core/actions/ChannelAccessCondition.java index fc8611a..f56d416 100644 --- a/ch.psi.fda/src/main/java/ch/psi/fda/core/actions/ChannelAccessCondition.java +++ b/ch.psi.fda/src/main/java/ch/psi/fda/core/actions/ChannelAccessCondition.java @@ -48,6 +48,9 @@ public class ChannelAccessCondition implements Action { private final Long timeout; + private volatile boolean abort = false; + private volatile Thread waitT = null; + /** * Constructor * @param channelName Name of the channel to set the value @@ -93,11 +96,20 @@ public class ChannelAccessCondition implements Action { */ @Override public void execute() throws InterruptedException { + abort=false; logger.finest("Checking channel "+channel.getName()+" for value "+expectedValue+" [timeout: "+timeout+"]" ); try{ + waitT = Thread.currentThread(); channel.waitForValue(expectedValue, timeout); // Workaround use 10seconds default set timeout to check several times whether the channel has reached the value } catch (CAException e) { throw new RuntimeException("Channel [name:"+channel.getName()+"] did not reach expected value "+expectedValue+" ", e); + } catch(InterruptedException e){ + if(!abort){ + throw e; + } + } + finally{ + waitT=null; } } @@ -106,7 +118,10 @@ public class ChannelAccessCondition implements Action { */ @Override public void abort() { - // This action cannot be aborted, therefore this method is not implemented + abort=true; + if(waitT!=null){ + waitT.interrupt(); + } } diff --git a/ch.psi.fda/src/main/java/ch/psi/fda/core/loops/ActorSensorLoop.java b/ch.psi.fda/src/main/java/ch/psi/fda/core/loops/ActorSensorLoop.java index 0d3978d..e06d02f 100644 --- a/ch.psi.fda/src/main/java/ch/psi/fda/core/loops/ActorSensorLoop.java +++ b/ch.psi.fda/src/main/java/ch/psi/fda/core/loops/ActorSensorLoop.java @@ -112,7 +112,8 @@ public class ActorSensorLoop implements ActionLoop { */ private Guard guard = null; - private boolean loop = false; + private volatile boolean loop = false; + private volatile boolean abort = false; private final boolean zigZag; @@ -168,6 +169,8 @@ public class ActorSensorLoop implements ActionLoop { */ @Override public void execute() throws InterruptedException { + abort = false; + /** * Thread pool for parallel execution of tasks */ @@ -224,6 +227,10 @@ public class ActorSensorLoop implements ActionLoop { action.execute(); } + if(abort){ // End loop if abort was issued + break; + } + // Set actors // for(Actor actor: actors){ // actor.set(); @@ -241,6 +248,10 @@ public class ActorSensorLoop implements ActionLoop { for(Action action: postActorActions){ action.execute(); } + + if(abort){ // End loop if abort was issued + break; + } } @@ -276,6 +287,10 @@ public class ActorSensorLoop implements ActionLoop { action.execute(); } + if(abort){ // End loop if abort was issued + break; + } + // Read sensors DataMessage message = new DataMessage(); for(Sensor sensor: sensors){ @@ -290,6 +305,10 @@ public class ActorSensorLoop implements ActionLoop { action.execute(); } + if(abort){ // End loop if abort was issued + break; + } + // Check guard if one is registered if(guard!=null){ guardOK=guard.check(); @@ -333,6 +352,7 @@ public class ActorSensorLoop implements ActionLoop { */ @Override public void abort(){ + abort = true; loop = false; // To abort all wait actions interrupt this thread diff --git a/ch.psi.fda/src/test/java/ch/psi/fda/aq/AcquisitionMainTest.java b/ch.psi.fda/src/test/java/ch/psi/fda/aq/AcquisitionMainTest.java new file mode 100644 index 0000000..9caa7e7 --- /dev/null +++ b/ch.psi.fda/src/test/java/ch/psi/fda/aq/AcquisitionMainTest.java @@ -0,0 +1,56 @@ +/** + * + * Copyright 2011 Paul Scherrer Institute. All rights reserved. + * + * This code is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * This code is distributed in the hope that it will be useful, but without any + * warranty; without even the implied warranty of merchantability or fitness for + * a particular purpose. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + * + */ +package ch.psi.fda.aq; + +import org.junit.After; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; + +/** + * @author ebner + * + */ +public class AcquisitionMainTest { + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() throws Exception { + } + + /** + * @throws java.lang.Exception + */ + @After + public void tearDown() throws Exception { + } + + /** + * Test method for {@link ch.psi.fda.aq.AcquisitionMain#main(java.lang.String[])}. + */ + @Ignore + @Test + public void testMain() { + System.setProperty("ch.psi.fda.home","src/test/resources/home"); + AcquisitionMain.main(new String[]{"src/test/resources/home/scans/templates/scan1d-waitError.xml"}); + } + +} diff --git a/ch.psi.fda/src/test/java/ch/psi/fda/core/actions/ChannelAccessConditionTest.java b/ch.psi.fda/src/test/java/ch/psi/fda/core/actions/ChannelAccessConditionTest.java index 07bd648..acf1ed4 100644 --- a/ch.psi.fda/src/test/java/ch/psi/fda/core/actions/ChannelAccessConditionTest.java +++ b/ch.psi.fda/src/test/java/ch/psi/fda/core/actions/ChannelAccessConditionTest.java @@ -174,5 +174,37 @@ public class ChannelAccessConditionTest { fail("Action did not return although the value was reached"); } } + + /** + * Test to ensure that the abort function is working correctly + * @throws CAException + * @throws InterruptedException + */ + @Test + public void testWaitAbort() throws CAException, InterruptedException { + final ChannelAccessCondition action = new ChannelAccessCondition(TestChannels.BINARY_OUT, 1, 10000l); + final ChannelBean channel = ChannelBeanFactory.getFactory().createChannelBean(Integer.class, TestChannels.BINARY_OUT, false); + + Thread t = new Thread(new Runnable() { + + @Override + public void run() { + try { + Thread.sleep(2000); + logger.info("Send abort ..."); + action.abort(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + }); + + // Set wait channel to 0 + channel.setValue(0); + + t.start(); + action.execute(); // timeouts after 10 seconds + + } }