/** * AnalyzerBeans * Copyright (C) 2014 Neopost - Customer Information Management * * This copyrighted material is made available to anyone wishing to use, modify, * copy, or redistribute it subject to the terms and conditions of the GNU * Lesser General Public License, as published by the Free Software Foundation. * * This program 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 distribution; if not, write to: * Free Software Foundation, Inc. * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ package org.eobjects.analyzer.job.concurrent; import java.util.concurrent.atomic.AtomicInteger; import org.eobjects.analyzer.job.tasks.Task; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Task listener that will wait (join) for a set of tasks to complete before * invoking onComplete(...) on a nested task listener. * * */ public final class JoinTaskListener implements TaskListener { private static final Logger logger = LoggerFactory.getLogger(ForkTaskListener.class); private final AtomicInteger _countDown; private final TaskListener _nestedTaskListener; private volatile Throwable _error; public JoinTaskListener(int tasksToWaitFor, TaskListener nestedTaskListener) { _nestedTaskListener = nestedTaskListener; if (tasksToWaitFor == 0) { logger.warn("Was asked to join execution after 0 tasks, this might be a bug. Continuing with immediate completion."); // immediate completion _countDown = new AtomicInteger(1); onComplete(null); } else { _countDown = new AtomicInteger(tasksToWaitFor); } } @Override public String toString() { return "Join[countDown=" + _countDown.get() + "]"; } @Override public void onBegin(Task task) { } @Override public void onComplete(Task task) { int count = _countDown.decrementAndGet(); logger.debug("onComplete(), count = {}", count); invokeNested(count, task); } @Override public void onError(Task task, Throwable throwable) { _error = throwable; int count = _countDown.decrementAndGet(); logger.debug("onComplete(), count = {}", count); invokeNested(count, task); } private void invokeNested(final int count, Task task) { if (count == 0) { if (_error == null) { logger.info("Calling onComplete(...) on nested TaskListener ()"); _nestedTaskListener.onComplete(task); } else { logger.info("Calling onError(...) on nested TaskListener ()"); _nestedTaskListener.onError(task, _error); } } } }