| /* |
| * Copyright (c) 2009-2013, 2015 Eike Stepper (Berlin, Germany) 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: |
| * Eike Stepper - initial API and implementation |
| */ |
| package org.eclipse.net4j.util.om.monitor; |
| |
| import org.eclipse.net4j.internal.util.bundle.OM; |
| import org.eclipse.net4j.util.concurrent.TrackableTimerTask; |
| import org.eclipse.net4j.util.om.OMPlatform; |
| |
| import java.util.Timer; |
| import java.util.TimerTask; |
| |
| /** |
| * @author Eike Stepper |
| * @since 2.0 |
| */ |
| public abstract class AbstractMonitor implements OMMonitor |
| { |
| private static final boolean CHECK_BEGIN = Boolean |
| .parseBoolean(OMPlatform.INSTANCE.getProperty("org.eclipse.net4j.util.om.monitor.CheckBegin", "false")); |
| |
| private static final long NOT_BEGUN = -1; |
| |
| private double totalWork = NOT_BEGUN; |
| |
| private double work; |
| |
| public AbstractMonitor() |
| { |
| } |
| |
| public boolean hasBegun() throws MonitorCanceledException |
| { |
| checkCanceled(); |
| return totalWork != NOT_BEGUN; |
| } |
| |
| public OMMonitor begin(double totalWork) throws MonitorCanceledException |
| { |
| checkCanceled(); |
| this.totalWork = totalWork; |
| return this; |
| } |
| |
| public OMMonitor begin() throws MonitorCanceledException |
| { |
| return begin(ONE); |
| } |
| |
| public void worked(double work) throws MonitorCanceledException |
| { |
| checkBegun(); |
| this.work += work; |
| } |
| |
| public void worked() throws MonitorCanceledException |
| { |
| worked(ONE); |
| } |
| |
| public OMMonitor fork(double work) |
| { |
| checkBegun(); |
| return createNestedMonitor(work); |
| } |
| |
| public OMMonitor fork() |
| { |
| return fork(ONE); |
| } |
| |
| public Async forkAsync(double work) |
| { |
| checkBegun(); |
| AsyncTimerTask asyncTimerTask = createAsyncTimerTask(work); |
| if (asyncTimerTask == null) |
| { |
| throw new NullPointerException("No async timer task has been created"); |
| } |
| |
| long period = getAsyncSchedulePeriod(); |
| scheduleAtFixedRate(asyncTimerTask, period, period); |
| return asyncTimerTask; |
| } |
| |
| public Async forkAsync() |
| { |
| return forkAsync(ONE); |
| } |
| |
| public void done() |
| { |
| if (!isCanceled()) |
| { |
| double rest = totalWork - work; |
| if (rest > 0) |
| { |
| worked(rest); |
| } |
| } |
| } |
| |
| public double getTotalWork() |
| { |
| return totalWork; |
| } |
| |
| public double getWork() |
| { |
| return work; |
| } |
| |
| public double getWorkPercent() |
| { |
| return percent(work, totalWork); |
| } |
| |
| protected OMMonitor createNestedMonitor(double work) |
| { |
| return new NestedMonitor(this, work); |
| } |
| |
| protected AsyncTimerTask createAsyncTimerTask(double work) |
| { |
| return new AsyncTimerTask(this, work, DEFAULT_TIME_FACTOR); |
| } |
| |
| protected abstract long getAsyncSchedulePeriod(); |
| |
| protected abstract Timer getTimer(); |
| |
| /** |
| * @since 3.0 |
| */ |
| protected abstract void scheduleAtFixedRate(TimerTask task, long delay, long period); |
| |
| private void checkBegun() throws MonitorCanceledException |
| { |
| if (CHECK_BEGIN && !hasBegun()) |
| { |
| throw new IllegalStateException("begin() has not been called"); //$NON-NLS-1$ |
| } |
| } |
| |
| /** |
| * @since 3.1 |
| */ |
| protected static double percent(double part, double whole) |
| { |
| return Math.min(part * HUNDRED / whole, HUNDRED); |
| } |
| |
| /** |
| * @author Eike Stepper |
| */ |
| public static class AsyncTimerTask extends TrackableTimerTask implements Async |
| { |
| private OMMonitor monitor; |
| |
| private boolean canceled; |
| |
| public AsyncTimerTask(AbstractMonitor parent, double parentWork, double timeFactor) |
| { |
| monitor = parent.fork(parentWork); |
| monitor.begin(); |
| } |
| |
| @Override |
| public void run() |
| { |
| try |
| { |
| if (!canceled && monitor != null) |
| { |
| double work = 1 - monitor.getWork(); |
| monitor.worked(work / TEN); |
| } |
| } |
| catch (Exception ex) |
| { |
| OM.LOG.error("AsyncTimerTask failed", ex); |
| } |
| } |
| |
| public void stop() |
| { |
| try |
| { |
| if (monitor != null) |
| { |
| monitor.done(); |
| } |
| |
| cancel(); |
| } |
| catch (Exception ex) |
| { |
| OM.LOG.error(ex); |
| } |
| } |
| |
| @Override |
| public boolean cancel() |
| { |
| canceled = true; |
| monitor = null; |
| return super.cancel(); |
| } |
| } |
| } |