package org.jactr.tools.experiment.trial.impl; /* * default logging */ import java.util.ArrayList; import java.util.Collection; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jactr.tools.experiment.IExperiment; import org.jactr.tools.experiment.trial.ITrial; import org.jactr.tools.experiment.triggers.ITrigger; public class Trial implements ITrial, Runnable { /** * Logger definition */ static private final transient Log LOGGER = LogFactory .getLog(Trial.class); private final String _id; private ITrigger _start; private ITrigger _end; private Collection<ITrigger> _triggers; private volatile boolean _isRunning; private volatile boolean _shouldStop = false; private Lock _lock = new ReentrantLock(); private Condition _runningCondition = _lock.newCondition(); private double _startTime; private double _stopTime; private IExperiment _experiment; public Trial(String id, IExperiment experiment) { _experiment = experiment; _id = id; _triggers = new ArrayList<ITrigger>(); } public IExperiment getExperiment() { return _experiment; } public String getId() { return _id; } public void addTrigger(ITrigger trigger) { _triggers.add(trigger); } public void setEndTrigger(ITrigger trigger) { _end = trigger; } public void setStartTrigger(ITrigger trigger) { _start = trigger; } public boolean isRunning() { try { _lock.lock(); return _isRunning; } finally { _lock.unlock(); } } private void setRunning(boolean running) { try { _lock.lock(); _isRunning = running; _runningCondition.signalAll(); } finally { _lock.unlock(); } } public void start() { if (isRunning()) throw new IllegalStateException(getId() + " is already running"); setRunning(true); started(); run(); } protected void started() { _startTime = _experiment.getTime(); if (_start != null) _start.setArmed(true); for (ITrigger trigger : _triggers) trigger.setArmed(true); } public void stop() { if (!isRunning()) { if (LOGGER.isWarnEnabled()) LOGGER.warn(String.format("%s is not running. Issuing stop anyway", getId())); } try { _lock.lock(); _shouldStop = true; _runningCondition.signalAll(); } finally { _lock.unlock(); } } protected boolean shouldStop() { return _shouldStop; } public void waitForStop() { try { _lock.lock(); if (!isRunning()) return; while (!_isRunning) _runningCondition.awaitUninterruptibly(); } finally { _lock.unlock(); } } public void run() { runInternal(); waitForStopSignal(); setRunning(false); stopped(); } protected void runInternal() { } protected void waitForStopSignal() { try { _lock.lock(); while (!_shouldStop) _runningCondition.awaitUninterruptibly(); _shouldStop = false; } finally { _lock.unlock(); } } protected void stopped() { _stopTime = _experiment.getTime(); if (_end != null) _end.setArmed(true); for (ITrigger trigger : _triggers) trigger.setArmed(false); setRunning(false); } public double getStartTime() { return _startTime; } public double getStopTime() { return _stopTime; } }