From e11bce7ad3e803e80883499fec0ad6e4540ffe43 Mon Sep 17 00:00:00 2001 From: Kristóf Marussy Date: Tue, 30 Jun 2020 18:03:48 +0200 Subject: Add modified VIATRA-DSE version --- .../org/eclipse/viatra/dse/base/GlobalContext.java | 374 +++++++++++++++++++++ 1 file changed, 374 insertions(+) create mode 100644 Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/GlobalContext.java (limited to 'Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/GlobalContext.java') diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/GlobalContext.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/GlobalContext.java new file mode 100644 index 00000000..7325ead3 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/GlobalContext.java @@ -0,0 +1,374 @@ +/******************************************************************************* + * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-v20.html. + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.viatra.dse.base; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.apache.log4j.Logger; +import org.eclipse.emf.common.notify.Notifier; +import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy; +import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategyFactory; +import org.eclipse.viatra.dse.designspace.api.IDesignSpace; +import org.eclipse.viatra.dse.multithreading.DSEThreadPool; +import org.eclipse.viatra.dse.objectives.IGlobalConstraint; +import org.eclipse.viatra.dse.objectives.IObjective; +import org.eclipse.viatra.dse.objectives.LeveledObjectivesHelper; +import org.eclipse.viatra.dse.solutionstore.SolutionStore; +import org.eclipse.viatra.dse.statecode.IStateCoderFactory; +import org.eclipse.viatra.dse.util.EMFHelper; +import org.eclipse.viatra.dse.visualizer.IDesignSpaceVisualizer; +import org.eclipse.viatra.transformation.evm.api.RuleSpecification; +import org.eclipse.viatra.transformation.evm.api.resolver.ConflictResolver; +import org.eclipse.viatra.transformation.evm.specific.ConflictResolvers; +import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +/** + * Creates new contexts for strategies. It is needed because of the multithreading. + * + * @author Andras Szabolcs Nagy + * + */ +public class GlobalContext { + + // **** fields and methods for multi threading *****// + // *************************************************// + + public enum ExplorationProcessState { + NOT_STARTED, + RUNNING, + STOPPING, + COMPLETED + } + + private ConcurrentLinkedQueue exceptions = new ConcurrentLinkedQueue(); + + private volatile ExplorationProcessState state = ExplorationProcessState.NOT_STARTED; + private final Set runningThreads = new HashSet(); + private DSEThreadPool threadPool = new DSEThreadPool(); + private int numberOfStartedThreads = 0; + private IDesignSpace designSpace; + + private AtomicBoolean firstThreadContextInited = new AtomicBoolean(false); + private AtomicBoolean firstThreadContextIniting = new AtomicBoolean(false); + + private Map, BatchTransformationRule> specificationRuleMap; + + private Object terminationSnycObject = new Object(); + + private Logger logger = Logger.getLogger(IStrategy.class); + + private boolean isAlreadyInited; + + public void waitForTermination() { + synchronized (terminationSnycObject) { + while (!isDone()) { + try { + terminationSnycObject.wait(); + } catch (InterruptedException e) { + } + } + } + } + + /** + * Starts a new thread to explore the design space. + * + * @param originalThreadContext The context of the thread which starts the new thread. + * @param model The model to start from. + * @param cloneModel It should be true in most cases. + * @param strategy The strategy, the thread will use. + * @return The {@link ExplorerThread} + */ + private synchronized ExplorerThread tryStartNewThread(ThreadContext originalThreadContext, Notifier model, + IStrategy strategy) { + + if(!isAlreadyInited) { + isAlreadyInited = true; + init(); + } + + if (state != ExplorationProcessState.COMPLETED && state != ExplorationProcessState.STOPPING + && threadPool.canStartNewThread()) { + + ThreadContext newThreadContext = new ThreadContext(this, strategy, model); + + // TODO : clone undo list? slave strategy can't go further back... + ExplorerThread explorerThread = new ExplorerThread(newThreadContext); + newThreadContext.setExplorerThread(explorerThread); + + boolean isSuccessful = threadPool.tryStartNewStrategy(explorerThread); + + if (isSuccessful) { + runningThreads.add(explorerThread); + + state = ExplorationProcessState.RUNNING; + ++numberOfStartedThreads; + + logger.info("New thread started, active threads: " + runningThreads.size()); + + return explorerThread; + } + } + return null; + } + + public synchronized ExplorerThread tryStartNewThread(ThreadContext originalThreadContext, IStrategy strategy) { + return tryStartNewThread(originalThreadContext, EMFHelper.clone(originalThreadContext.getModel()), strategy); + } + + public synchronized ExplorerThread tryStartNewThreadWithoutModelClone(ThreadContext originalThreadContext, + IStrategy strategy) { + return tryStartNewThread(originalThreadContext, originalThreadContext.getModel(), strategy); + } + + public synchronized ExplorerThread startFirstThread(IStrategy strategy, Notifier model) { + Preconditions.checkState(!isAlreadyInited, "First thread is already started."); + return tryStartNewThread(null, EMFHelper.clone(model), strategy); + } + + public synchronized ExplorerThread startFirstThreadWithoutModelClone(IStrategy strategy, Notifier model) { + Preconditions.checkState(!isAlreadyInited, "First thread is already started."); + return tryStartNewThread(null, model, strategy); + } + + public synchronized void startAllThreads(ThreadContext originalThreadContext, IStrategyFactory strategyFactory) { + while (canStartNewThread()) { + tryStartNewThread(originalThreadContext, strategyFactory.createStrategy()); + } + } + + /** + * Starts a new thread to explore the design space. + * + * @param strategyBase + * The {@link Strategy}. + * @param tedToClone + * The model to clone. Hint: context.getTed() + */ + + public synchronized void strategyFinished(ExplorerThread strategy) { + runningThreads.remove(strategy); + + logger.info("Thread finished, active threads: " + runningThreads.size()); + + // is the first part necessary? + if (runningThreads.isEmpty()) { + state = ExplorationProcessState.COMPLETED; + threadPool.shutdown(); + + // if the main thread (which started the exploration) + // is waiting for the solution, than wake it up + synchronized (terminationSnycObject) { + terminationSnycObject.notify(); + logger.info("Exploration terminated."); + } + + } + } + + public synchronized boolean isDone() { + return state == ExplorationProcessState.COMPLETED && runningThreads.isEmpty(); + } + + public synchronized boolean isNotStarted() { + return state == ExplorationProcessState.NOT_STARTED; + } + + public boolean canStartNewThread() { + return (state == ExplorationProcessState.NOT_STARTED || state == ExplorationProcessState.RUNNING) + && threadPool.canStartNewThread(); + } + + public synchronized void stopAllThreads() { + if (state == ExplorationProcessState.RUNNING) { + state = ExplorationProcessState.STOPPING; + logger.info("Stopping all threads."); + for (ExplorerThread strategy : runningThreads) { + strategy.stopRunning(); + } + } + } + + public void registerException(Throwable e) { + exceptions.add(e); + } + + // ******* fields and methods for exploration *******// + // **************************************************// + + private List objectives = new ArrayList(); + private IObjective[][] leveledObjectives; + private List globalConstraints = new ArrayList(); + private Set> transformations = new HashSet>(); + private IStateCoderFactory stateCoderFactory; + private SolutionStore solutionStore = new SolutionStore(1); + private Object sharedObject; + private List visualizers; + + private ConflictResolver conflictResolver = ConflictResolvers.createArbitraryResolver(); + + private void init() { + leveledObjectives = new LeveledObjectivesHelper(objectives).initLeveledObjectives(); + + specificationRuleMap = new HashMap<>(); + for (BatchTransformationRule rule : transformations) { + specificationRuleMap.put(rule.getRuleSpecification(), rule); + } + } + + public List getVisualizers() { + return ImmutableList.copyOf(visualizers); + } + + public void registerDesignSpaceVisualizer(IDesignSpaceVisualizer visualizer) { + if (visualizer == null) { + return; + } + if (visualizers == null) { + visualizers = new ArrayList(); + } + visualizers.add(visualizer); + } + + public void deregisterDesignSpaceVisualizer(IDesignSpaceVisualizer visualizer) { + if (visualizer == null) { + return; + } + if (visualizers != null) { + visualizers.remove(visualizer); + } + } + + public boolean isDesignSpaceVisualizerRegistered(IDesignSpaceVisualizer visualizer) { + if (visualizers != null) { + return visualizers.contains(visualizer); + } + return false; + } + + public void initVisualizersForThread(ThreadContext threadContext) { + if (visualizers != null && !visualizers.isEmpty()) { + for (IDesignSpaceVisualizer visualizer : visualizers) { + visualizer.init(threadContext); + threadContext.getDesignSpaceManager().registerExploreEventHandler(visualizer); + } + } + } + + public boolean isExceptionHappendInOtherThread() { + return !exceptions.isEmpty(); + } + + public Collection getExceptions() { + return exceptions; + } + + public IStateCoderFactory getStateCoderFactory() { + return stateCoderFactory; + } + + public void setStateCoderFactory(IStateCoderFactory stateCoderFactory) { + this.stateCoderFactory = stateCoderFactory; + } + + public Set> getTransformations() { + return transformations; + } + + public void setTransformations(Set> transformations) { + this.transformations = transformations; + } + + public DSEThreadPool getThreadPool() { + return threadPool; + } + + public IDesignSpace getDesignSpace() { + return designSpace; + } + + public void setDesignSpace(IDesignSpace designSpace) { + this.designSpace = designSpace; + } + + public int getNumberOfStartedThreads() { + return numberOfStartedThreads; + } + + public Object getSharedObject() { + return sharedObject; + } + + public void setSharedObject(Object sharedObject) { + this.sharedObject = sharedObject; + } + + public ExplorationProcessState getState() { + return state; + } + + public List getObjectives() { + return objectives; + } + + public void setObjectives(List objectives) { + this.objectives = objectives; + } + + public List getGlobalConstraints() { + return globalConstraints; + } + + public void setGlobalConstraints(List globalConstraints) { + this.globalConstraints = globalConstraints; + } + + AtomicBoolean getFirstThreadContextInited() { + return firstThreadContextInited; + } + + AtomicBoolean getFirstThreadContextIniting() { + return firstThreadContextIniting; + } + + public IObjective[][] getLeveledObjectives() { + return leveledObjectives; + } + + public void setSolutionStore(SolutionStore solutionStore) { + this.solutionStore = solutionStore; + } + + public SolutionStore getSolutionStore() { + return solutionStore; + } + + public Map, BatchTransformationRule> getSpecificationRuleMap() { + return specificationRuleMap; + } + + public void setConflictResolver(ConflictResolver conflictResolver) { + this.conflictResolver = conflictResolver; + } + + public ConflictResolver getConflictResolver() { + return conflictResolver; + } +} -- cgit v1.2.3-54-g00ecf