/* * Copyright (c) 2007 BUSINESS OBJECTS SOFTWARE LIMITED * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of Business Objects nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * RTExecutionContext.java * Created: Dec 7, 2004 * By: RCypher */ package org.openquark.cal.internal.runtime.lecc; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicInteger; import org.openquark.cal.compiler.ModuleName; import org.openquark.cal.compiler.QualifiedName; import org.openquark.cal.internal.runtime.ExecutionContextImpl; import org.openquark.cal.internal.runtime.RuntimeEnvironment; import org.openquark.cal.runtime.ExecutionContextProperties; /** * This is the class the lecc machine uses to track execution statistics. * It is also used to associate state with a thread of execution. * Currently this state consists of cached CAF values. * @author RCypher */ public final class RTExecutionContext extends ExecutionContextImpl { private static final int ACTION_CONTINUE = 0; private static final int ACTION_QUIT = 1; // Some member/methods used for collecting runtime statistics. //Since the execution context can be accessed by multiple threads while executing in concurrency enabled mode, //these must be synchronized. private final AtomicInteger nReductions = new AtomicInteger(-1); private final AtomicInteger nMethodCalls = new AtomicInteger(-1); private final AtomicInteger nDataTypeInstances = new AtomicInteger(-1); //use ConcurretMap/AtomicInteger to get synchronization + efficient creation of count objects private final ConcurrentMap<QualifiedName, AtomicInteger> callCounts = new ConcurrentHashMap<QualifiedName, AtomicInteger>(); private final ConcurrentMap<QualifiedName, AtomicInteger> dcConstructorCounts = new ConcurrentHashMap<QualifiedName, AtomicInteger>(); private final ConcurrentMap<QualifiedName, AtomicInteger> dcFunctionCounts = new ConcurrentHashMap<QualifiedName, AtomicInteger>(); /** * Used by the client to tell the executor to stop prematurely. * Must be marked as volatile (or have access to it synchronized) even though read/writes of * ints are guaranteed to be atomic. See Effective Java item 48 pg 191. * We limit direct checking of quit (see the code below) since it can be quite expensive to * access a volatile field. */ private volatile int continueAction = ACTION_CONTINUE; /** * Internal flag for tracking the number of times that a client tries to check the quit flag. * We use this to limit actually accessing the volatile boolean, since this can be quite expensive. */ private int checkQuitCount = 0; /** Interval at which the actual volatile boolean quit flag is accessed. */ private static final int CHECK_QUIT_INTERVAL = 20; /** * Constructs an instance of this class with the specified properties. * @param properties the properties to be associated with the execution context. * @param runtimeEnvironment */ public RTExecutionContext(ExecutionContextProperties properties, RuntimeEnvironment runtimeEnvironment) { super(properties, runtimeEnvironment); } /** * Request that the runtime terminate evaluation. */ public void requestQuit () { continueAction = ACTION_QUIT; } /** * Request that the runtime suspend evaluation. */ public void requestSuspend() { setStepAllThreads(true); setStepping(true); } /** * Was the runtime asked to quit? Note that if SourceGenerationConfiguration.NON_INTERRUPTIBLE_RUNTIME * is true then even if a quit was requested, the runtime will ignore this request. * Creation date: (3/21/02 2:18:40 PM) * @return boolean */ public boolean isQuitRequested() { if (checkQuitCount++ > CHECK_QUIT_INTERVAL) { checkQuitCount = 0; if (continueAction == ACTION_CONTINUE) { return false; } else if (continueAction == ACTION_QUIT) { return true; } } return false; } /* * Some methods used to track runtime statistics. */ public final void incrementNReductions(){ nReductions.incrementAndGet(); } public final void incrementNMethodCalls(){ nMethodCalls.incrementAndGet(); } public final void incrementNDataTypeInstances(){ nDataTypeInstances.incrementAndGet(); } public final void scCalled (String moduleName, String unqualifiedName) { incrementCounts(moduleName, unqualifiedName, callCounts); } public final void dcConstructorCalled (String moduleName, String unqualifiedName) { incrementCounts(moduleName, unqualifiedName, dcConstructorCounts); } public final void dcFunctionCalled (String moduleName, String unqualifiedName) { incrementCounts(moduleName, unqualifiedName, dcFunctionCounts); } private static void incrementCounts( final String moduleName, final String unqualifiedName, final ConcurrentMap<QualifiedName, AtomicInteger> countsMap) { final QualifiedName qualifiedName = QualifiedName.make(ModuleName.make(moduleName), unqualifiedName); AtomicInteger callCount = countsMap.get(qualifiedName); if (callCount != null) { callCount.incrementAndGet(); } else { callCount = countsMap.putIfAbsent(qualifiedName, new AtomicInteger(1)); if (callCount != null) { callCount.incrementAndGet(); } } } /** * @return Returns the nReductions. */ public final int getNReductions() { return nReductions.get(); } /** * @return Returns the nMethodCalls. */ public final int getNMethodCalls() { return nMethodCalls.get(); } /** * @return Returns the nDataTypeInstances. */ public final int getNDataTypeInstances() { return nDataTypeInstances.get(); } /** * @return Returns the callCounts. This is a copy and can be freely modified. */ public final Map<QualifiedName, Integer> getCallCounts() { return copyMap(callCounts); } /** * @return Returns the dcConstructorCounts. This is a copy and can be freely modified. */ public final Map<QualifiedName, Integer> getDcConstructorCounts() { return copyMap(dcConstructorCounts); } /** * @return Returns the dcFunctionCounts. This is a copy and can be freely modified. */ public final Map<QualifiedName, Integer> getDcFunctionCounts() { return copyMap(dcFunctionCounts); } private static Map<QualifiedName, Integer> copyMap(ConcurrentMap<QualifiedName, AtomicInteger> map) { Map<QualifiedName, Integer> result = new HashMap<QualifiedName, Integer>(); for (Map.Entry<QualifiedName, AtomicInteger> entry : map.entrySet()) { result.put(entry.getKey(), entry.getValue().intValue()); } return result; } /** * Reset the fields of the execution context. * @param newRuntimeEnvironment */ public void reset (RuntimeEnvironment newRuntimeEnvironment) { if (newRuntimeEnvironment == null) { throw new NullPointerException("Invalid RuntimeEnvironment reference in RTExecutionContext."); } nReductions.set(-1); nMethodCalls.set(-1); nDataTypeInstances.set(-1); callCounts.clear(); dcConstructorCounts.clear(); dcFunctionCounts.clear(); continueAction = ACTION_CONTINUE; setRuntimeEnvironment(newRuntimeEnvironment); } /** * Null out the super.runtimeEnvironment field. * This prevents the execution context from holding on to * an out-of-date instance of RuntimeEnvironment. */ public void clearRuntimeEnvironment() { setRuntimeEnvironment(null); } }