(1) Enabled support for building with VS 2015. (2) Added tunload to unload

tasks from command line. (3) Fixed memory leak in maps due to threadlocal
storage; replaced with spinlocks for thread-safe reads.
This commit is contained in:
ejackson 2015-11-20 19:28:30 -06:00
Родитель fae5147888
Коммит 4016e05627
6 изменённых файлов: 114 добавлений и 10 удалений

Просмотреть файл

@ -264,6 +264,18 @@
var subKey = Environment.Is64BitOperatingSystem ? RegVS64SubKey : RegVS32SubKey;
string installDir = null;
//// Try to get version 14
if (installDir == null)
{
using (var key = Registry.LocalMachine.OpenSubKey(string.Format(subKey, 14)))
{
if (key != null)
{
installDir = key.GetValue("ProductDir") as string;
}
}
}
//// Try to get version 12
if (installDir == null)
{

Просмотреть файл

@ -36,8 +36,9 @@
private const string SaveMsg = "Saves the module modname into file.";
private const string LSInfoMsg = "Lists environment objects. Use: ls [vars | progs | tasks]";
private const string LoadMsg = "Loads and compiles a file that is not yet loaded. Use: load filename";
private const string UnloadMsg = "Unloads and an installed program and all dependent programs. Use: unload [prog | *]";
private const string ReloadMsg = "Reloads and an installed program and all dependent programs. Use: reload [prog | *]";
private const string UnloadMsg = "Unloads an installed program and all dependent programs. Use: unload [prog | *]";
private const string TUnloadMsg = "Unloads a task. Use: tunload [id | *]";
private const string ReloadMsg = "Reloads an installed program and all dependent programs. Use: reload [prog | *]";
private const string PrintMsg = "Prints the installed program with the given name. Use: print progname";
private const string DetailsMsg = "Prints details about the compiled module with the given name. Use: det modname";
private const string TypesMsg = "Prints inferred variable types. Use: types modname";
@ -225,6 +226,10 @@
cmdMap.Add(ulCmd.Name, ulCmd);
cmdMap.Add(ulCmd.ShortName, ulCmd);
var tulCmd = new Command("tunload", "tul", DoTUnload, TUnloadMsg);
cmdMap.Add(tulCmd.Name, tulCmd);
cmdMap.Add(tulCmd.ShortName, tulCmd);
var rlCmd = new Command("reload", "rl", DoReload, ReloadMsg);
cmdMap.Add(rlCmd.Name, rlCmd);
cmdMap.Add(rlCmd.ShortName, rlCmd);
@ -505,6 +510,29 @@
}
}
private void DoTUnload(string s)
{
s = s.Trim();
int taskId;
if (!int.TryParse(s, out taskId) && s != "*")
{
sink.WriteMessageLine(TUnloadMsg, SeverityKind.Warning);
}
else if (s == "*")
{
var cnt = taskManager.UnloadTasks();
sink.WriteMessageLine(string.Format("Unloaded {0} tasks", cnt));
}
else if (taskManager.TryUnloadTask(taskId))
{
sink.WriteMessageLine(string.Format("Unloaded task {0}", taskId));
}
else
{
sink.WriteMessageLine(string.Format("No task with ID {0}", taskId), SeverityKind.Warning);
}
}
private void DoStats(string s)
{
var cmdParts = s.Split(cmdSplitChars, 2, StringSplitOptions.RemoveEmptyEntries);

Просмотреть файл

@ -47,6 +47,26 @@
return true;
}
public int UnloadTasks()
{
var unloadCount = tasks.Count;
tasks.Clear();
GC.Collect();
return unloadCount;
}
public bool TryUnloadTask(int id)
{
if (!tasks.ContainsKey(id))
{
return false;
}
tasks.Remove(id);
GC.Collect();
return true;
}
public bool TryGetStatistics(int id, out ExecuterStatistics stats)
{
TaskData data;

Просмотреть файл

@ -1292,6 +1292,8 @@
programDeps = nextDeps;
FileRoot = newFileRoot;
EnvRoot = newEnvRoot;
GC.Collect();
}
private IEnumerable<ProgramName> EnumeratePrograms(DependencyCollection<ProgramName, Unit>.IDependencyNode n)

Просмотреть файл

@ -11,9 +11,10 @@
/// </summary>
public class Map<S, T> : IEnumerable<KeyValuePair<S, T>>
{
private Comparison<S> comparer;
private SpinLock lastFoundLock = new SpinLock();
private Node lastFoundNode = null;
private ThreadLocal<Node> lastFound = new ThreadLocal<Node>();
private Comparison<S> comparer;
private int numberOfKeys = 0;
@ -21,6 +22,43 @@
private Node root = null;
private Node LastFound
{
get
{
bool gotLock = false;
try
{
lastFoundLock.Enter(ref gotLock);
return lastFoundNode;
}
finally
{
if (gotLock)
{
lastFoundLock.Exit();
}
}
}
set
{
bool gotLock = false;
try
{
lastFoundLock.Enter(ref gotLock);
lastFoundNode = value;
}
finally
{
if (gotLock)
{
lastFoundLock.Exit();
}
}
}
}
public Map(Comparison<S> comparer)
{
this.comparer = comparer;
@ -187,7 +225,7 @@
numberOfKeys = 0;
phantomList.Clear();
root = null;
lastFound.Value = null;
LastFound = null;
}
[Pure]
@ -413,9 +451,11 @@
public bool TryFindValue(S key, out T value)
{
if (lastFound.Value != null && Compare(lastFound.Value, key) == 0)
var lastFound = LastFound;
if (lastFound != null && Compare(lastFound, key) == 0)
{
value = lastFound.Value.Value;
value = lastFound.Value;
return true;
}
@ -427,7 +467,7 @@
if (cmp == 0)
{
value = checkNode.Value;
lastFound.Value = checkNode;
LastFound = checkNode;
return true;
}
else if (cmp > 0)
@ -446,7 +486,7 @@
public bool Remove(S key)
{
lastFound.Value = null;
LastFound = null;
Node deletePos = FindNearestNode(key);
if (deletePos == null || Compare(deletePos, key) != 0)
{

Просмотреть файл

@ -73,8 +73,10 @@
public SubtermMatcher(TermIndex index, bool onlyNewKinds, Term[] pattern)
{
Contract.Requires(index != null);
Contract.Requires(pattern != null && pattern.Length > 0);
//// Appears that Requires is triggering bug in Code Contracts 1.9.10714.2
Contract.Assert(index != null);
this.pattern = pattern;
IsMatchOnlyNewKinds = onlyNewKinds;
matchingUnions = new AppFreeCanUnn[pattern.Length];