import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
-import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
import org.simantics.scl.compiler.module.ImportDeclaration;
import org.simantics.scl.compiler.module.Module;
import org.simantics.scl.compiler.module.options.ModuleCompilationOptionsAdvisor;
+import org.simantics.scl.compiler.module.repository.UpdateListener.Observable;
import org.simantics.scl.compiler.runtime.RuntimeEnvironment;
import org.simantics.scl.compiler.runtime.RuntimeEnvironmentImpl;
import org.simantics.scl.compiler.runtime.RuntimeModule;
PENDING_MODULES.get().remove(moduleName);
}
- private class ModuleEntry implements UpdateListener {
+ private class ModuleEntry extends UpdateListener implements Observable {
final String moduleName;
- WeakHashMap<UpdateListener,Object> listeners = new WeakHashMap<UpdateListener,Object>();
+ THashSet<UpdateListener> listeners = new THashSet<UpdateListener>();
ModuleSource source;
Failable<Module> compilationResult;
}
synchronized void addListener(UpdateListener listener) {
- if(listener != null)
- listeners.put(listener, null);
+ if(listener == null || listeners == null)
+ return;
+ listeners.add(listener);
+ listener.addObservable(this);
+ }
+
+ public synchronized void removeListener(UpdateListener listener) {
+ if (listeners == null)
+ return;
+ listeners.remove(listener);
}
@Override
public void notifyAboutUpdate() {
- if (listeners == null)
- return;
ArrayList<UpdateListener> externalListeners = new ArrayList<UpdateListener>();
notifyAboutUpdate(externalListeners);
for(UpdateListener listener : externalListeners)
}
synchronized void notifyAboutUpdate(ArrayList<UpdateListener> externalListeners) {
+ stopListening();
+ if (listeners == null)
+ return;
if(moduleCache.get(moduleName) == this) {
moduleCache.remove(moduleName);
if(SCLCompilerConfiguration.TRACE_MODULE_UPDATE) {
System.out.println("Invalidate " + moduleName);
- for(UpdateListener l : listeners.keySet())
+ for(UpdateListener l : listeners)
System.out.println(" " + l);
}
- for(UpdateListener l : listeners.keySet())
+ THashSet<UpdateListener> listenersCopy = listeners;
+ listeners = null;
+ for(UpdateListener l : listenersCopy)
+ l.stopListening();
+ for(UpdateListener l : listenersCopy)
if(l instanceof ModuleEntry)
((ModuleEntry)l).notifyAboutUpdate(externalListeners);
- else
+ else {
externalListeners.add(l);
+ }
}
}
if(parentModule != null)
parentModules.add(parentModule);
}*/
- RuntimeModule rm = new RuntimeModule(module, parentModules, source.getClassLoader());
+ RuntimeModule rm = new RuntimeModule(module, parentModules, module.getParentClassLoader());
ModuleInitializer initializer = module.getModuleInitializer();
if(initializer != null)
try {
return runtimeModule;
}
- public void dispose() {
+ public synchronized void dispose() {
if (listeners != null)
listeners.clear();
listeners = null;
+ stopListening();
source = null;
compilationResult = null;
if (runtimeModule != null) {
public Failable<RuntimeModule> getRuntimeModule(String moduleName) {
return getRuntimeModule(moduleName, null);
}
-
+
private ModuleEntry getModuleEntry(String moduleName, UpdateListener listener) {
/* It is deliberate that the following code does not try to prevent
* simultaneous compilation of the same module. This is because in
THashMap<String, ModuleEntry> result = new THashMap<String, ModuleEntry>();
Collection<ImportFailure> failures = null;
+ THashSet<String> originalImports = new THashSet<String>();
ArrayList<ImportDeclaration> stack = new ArrayList<ImportDeclaration>(imports.length);
- for(ImportDeclaration import_ : imports)
+ for(ImportDeclaration import_ : imports) {
stack.add(import_);
+ originalImports.add(import_.moduleName);
+ }
while(!stack.isEmpty()) {
ImportDeclaration import_ = stack.remove(stack.size()-1);
if(!result.containsKey(import_.moduleName)) {
- ModuleEntry entry = getModuleEntry(import_.moduleName, listener);
+ ModuleEntry entry = getModuleEntry(import_.moduleName, originalImports.contains(import_.moduleName) ? listener : null);
Failable<Module> compilationResult = entry.compilationResult;
if(compilationResult.didSucceed()) {
result.put(import_.moduleName, entry);
public void setAdvisor(ModuleCompilationOptionsAdvisor advisor) {
this.advisor = advisor;
}
-\r
+
}
\ No newline at end of file