blob: 310b4011ef16d1237beeddf81cfcc15886ae4f5b [file] [log] [blame]
// Copyright (C) 2011 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.rules;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.assistedinject.Assisted;
import com.googlecode.prolog_cafe.lang.BufferingPrologControl;
import com.googlecode.prolog_cafe.lang.Prolog;
import com.googlecode.prolog_cafe.lang.PrologMachineCopy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
* Per-thread Prolog interpreter.
* <p>
* This class is not thread safe.
* <p>
* A single copy of the Prolog interpreter, for the current thread.
*/
public class PrologEnvironment extends BufferingPrologControl {
private static final Logger log =
LoggerFactory.getLogger(PrologEnvironment.class);
static final int MAX_ARITY = 8;
public static interface Factory {
/**
* Construct a new Prolog interpreter.
*
* @param src the machine to template the new environment from.
* @return the new interpreter.
*/
PrologEnvironment create(PrologMachineCopy src);
}
private final Injector injector;
private final Map<StoredValue<Object>, Object> storedValues;
private List<Runnable> cleanup;
@Inject
PrologEnvironment(Injector i, @Assisted PrologMachineCopy src) {
super(src);
injector = i;
setMaxArity(MAX_ARITY);
setEnabled(EnumSet.allOf(Prolog.Feature.class), false);
storedValues = new HashMap<StoredValue<Object>, Object>();
cleanup = new LinkedList<Runnable>();
}
/** Get the global Guice Injector that configured the environment. */
public Injector getInjector() {
return injector;
}
/**
* Lookup a stored value in the interpreter's hash manager.
*
* @param <T> type of stored Java object.
* @param sv unique key.
* @return the value; null if not stored.
*/
@SuppressWarnings("unchecked")
public <T> T get(StoredValue<T> sv) {
return (T) storedValues.get(sv);
}
/**
* Set a stored value on the interpreter's hash manager.
*
* @param <T> type of stored Java object.
* @param sv unique key.
* @param obj the value to store under {@code sv}.
*/
@SuppressWarnings("unchecked")
public <T> void set(StoredValue<T> sv, T obj) {
storedValues.put((StoredValue<Object>) sv, obj);
}
/**
* Copy the stored values from another interpreter to this one.
* Also gets the cleanup from the child interpreter
*/
public void copyStoredValues(PrologEnvironment child) {
storedValues.putAll(child.storedValues);
setCleanup(child.cleanup);
}
/**
* Assign the environment a cleanup list (in order to use a centralized list)
* If this enivronment's list is non-empty, append its cleanup tasks to the
* assigning list.
*/
public void setCleanup(List<Runnable> newCleanupList) {
newCleanupList.addAll(cleanup);
cleanup = newCleanupList;
}
/**
* Adds cleanup task to run when close() is called
* @param task is run when close() is called
*/
public void addToCleanup(Runnable task) {
cleanup.add(task);
}
/**
* Release resources stored in interpreter's hash manager.
*/
public void close() {
for (final Iterator<Runnable> i = cleanup.iterator(); i.hasNext();) {
try {
i.next().run();
} catch (Throwable err) {
log.error("Failed to execute cleanup for PrologEnvironment", err);
}
i.remove();
}
}
}