001 /*
002 * Java Genetic Algorithm Library (jenetics-3.7.0).
003 * Copyright (c) 2007-2016 Franz Wilhelmstötter
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 *
017 * Author:
018 * Franz Wilhelmstötter (franz.wilhelmstoetter@gmx.at)
019 */
020 package org.jenetics.tool.evaluation;
021
022 import static java.util.Objects.requireNonNull;
023
024 import java.io.Console;
025 import java.nio.file.Path;
026 import java.util.concurrent.atomic.AtomicBoolean;
027 import java.util.function.Supplier;
028
029 import org.jenetics.internal.util.require;
030
031 import org.jenetics.tool.trial.Trial;
032 import org.jenetics.tool.trial.TrialMeter;
033
034 /**
035 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
036 * @version 3.5
037 * @since 3.5
038 */
039 public abstract class AbstractRunner<P> {
040
041 private final Supplier<TrialMeter<P>> _trialMeter;
042 private final int _sampleCount;
043 private final Path _resultPath;
044
045 private volatile Thread _trialThread = null;
046 private final AtomicBoolean _stop = new AtomicBoolean(false);
047
048 protected AbstractRunner(
049 final Supplier<TrialMeter<P>> trialMeter,
050 final int sampleCount,
051 final Path resultPath
052 ) {
053 _trialMeter = requireNonNull(trialMeter);
054 _sampleCount = require.positive(sampleCount);
055 _resultPath = requireNonNull(resultPath);
056 }
057
058 protected abstract double[] fitness(final P param);
059
060 public void start() {
061 if (_trialThread != null) {
062 throw new IllegalStateException("Trial thread already running.");
063 }
064
065 final Trial<P> trial = new Trial<>(
066 this::fitness,
067 _trialMeter,
068 count -> count >= _sampleCount || _stop.get(),
069 _resultPath
070 );
071
072 _trialThread = new Thread(trial);
073 _trialThread.start();
074 }
075
076 public void join() throws InterruptedException {
077 if (_trialThread == null) {
078 throw new IllegalStateException("Trial thread is not running.");
079 }
080
081 try {
082 final Console console = System.console();
083 if (console != null) {
084 final Thread interrupter = new Thread(() -> {
085 String command;
086 do {
087 command = console.readLine();
088 Trial.info("Got command '" + command + "'");
089 } while (!"exit".equals(command));
090
091 Trial.info("Stopping trial...");
092 _trialThread.interrupt();
093 });
094 interrupter.setName("Console read thread");
095 interrupter.setDaemon(true);
096 interrupter.start();
097 }
098
099 _trialThread.join();
100 Trial.info("Sopped trial.");
101 } finally {
102 _trialThread = null;
103 }
104 }
105
106 }
|