public static void BeginAddOrUpdatePaths(IEnumerable <string> basePaths, bool skipFunctionBodies = false, ParseFinishedHandler finishedHandler = null) { if (basePaths == null) { throw new ArgumentNullException("basePaths"); } if (System.Diagnostics.Debugger.IsAttached) { Console.WriteLine("BeginAddOrUpdatePaths: "); foreach (var p in basePaths) { Console.WriteLine(p); } Console.WriteLine("---------"); } GC.Collect(); parseCompletedEvent.Reset(); stopParsing = false; var c = basePaths.Count(); if (c == 0) { var im = new StatIntermediate(); if (finishedHandler != null) { im.parseSubTasksUntilFinished.Add(new ParseSubtaskContainer(1, finishedHandler)); } im.completed.Set(); Interlocked.Increment(ref parsingThreads); noticeFinish(new ParseIntermediate(im, null, null)); return; } var countObj = new ParseSubtaskContainer(c, finishedHandler); foreach (var path in basePaths) { Interlocked.Increment(ref parsingThreads); basePathQueue.Push(new PathQueueArgs(path, skipFunctionBodies, countObj)); } preparationThreadStartEvent.Set(); LaunchPreparationThread(); }
static void preparationTh () { while (true) { if (basePathQueue.IsEmpty && !preparationThreadStartEvent.WaitOne (ThreadWaitTimeout)) return; PathQueueArgs tup; while (basePathQueue.TryPop(out tup)) { if (stopParsing) break; var path = tup.basePath; if (!Directory.Exists (path)) continue; // Is it okay to directly skip it w/o calling noticeFinished? StatIntermediate statIm; // Check if path is being parsed currently. { criticalPreparationSection.WaitOne (); if (ParseStatistics.TryGetValue (path, out statIm)) { if(tup.finished_untilCount != null) statIm.parseSubTasksUntilFinished.Add (tup.finished_untilCount); if (Interlocked.Decrement (ref parsingThreads) < 1) throw new InvalidOperationException ("Race-condition during parse process: There must be two or more parse tasks active!"); criticalPreparationSection.Set (); continue; } ParseStatistics [path] = statIm = new StatIntermediate { skipFunctionBodies = tup.skipFunctionBodies, basePath = path, }; if(tup.finished_untilCount != null) statIm.parseSubTasksUntilFinished.Add (tup.finished_untilCount); criticalPreparationSection.Set (); } // Check if it's necessary to reparse the directory RootPackage oldRoot; if (ParsedDirectories.TryGetValue (path, out oldRoot) && oldRoot.LastParseTime >= Directory.GetLastWriteTimeUtc (path)) { noticeFinish (new ParseIntermediate (statIm, oldRoot, string.Empty)); continue; } statIm.sw.Restart (); //ISSUE: wild card character ? seems to behave differently across platforms // msdn: -> Exactly zero or one character. // monodocs: -> Exactly one character. var files = Directory.GetFiles (path, "*.d", SearchOption.AllDirectories); var ifiles = Directory.GetFiles (path, "*.di", SearchOption.AllDirectories); statIm.totalFiles = statIm.remainingFiles = files.Length + ifiles.Length; var newRoot = new RootPackage { LastParseTime = Directory.GetLastWriteTimeUtc(path) }; if (statIm.totalFiles == 0) { noticeFinish (new ParseIntermediate (statIm, newRoot, string.Empty)); continue; } parseThreadStartEvent.Set (); LaunchParseThreads (); if (files.Length != 0) foreach (string file in files) queue.Push (new ParseIntermediate (statIm, newRoot, file)); if (ifiles.Length != 0) foreach (string ifile in ifiles) queue.Push (new ParseIntermediate (statIm, newRoot,ifile)); parseThreadStartEvent.Reset (); } } }
public static void BeginAddOrUpdatePaths (IEnumerable<string> basePaths, bool skipFunctionBodies = false, ParseFinishedHandler finishedHandler = null) { if (basePaths == null) throw new ArgumentNullException ("basePaths"); if (System.Diagnostics.Debugger.IsAttached) { Console.WriteLine ("BeginAddOrUpdatePaths: "); foreach (var p in basePaths) Console.WriteLine (p); Console.WriteLine ("---------"); } GC.Collect (); parseCompletedEvent.Reset (); stopParsing = false; var c = basePaths.Count (); if (c == 0) { var im = new StatIntermediate(); if(finishedHandler!=null) im.parseSubTasksUntilFinished.Add (new ParseSubtaskContainer(1,finishedHandler)); im.completed.Set (); Interlocked.Increment (ref parsingThreads); noticeFinish (new ParseIntermediate (im, null, null)); return; } var countObj = new ParseSubtaskContainer (c, finishedHandler); foreach (var path in basePaths) { Interlocked.Increment (ref parsingThreads); basePathQueue.Push (new PathQueueArgs (path, skipFunctionBodies, countObj)); } preparationThreadStartEvent.Set (); LaunchPreparationThread (); }
public ParseIntermediate (StatIntermediate im, RootPackage r, string f) { this.im = im; root = r; file = f; }
static void preparationTh() { while (true) { if (basePathQueue.IsEmpty && !preparationThreadStartEvent.WaitOne(ThreadWaitTimeout)) { return; } PathQueueArgs tup; while (basePathQueue.TryPop(out tup)) { if (stopParsing) { break; } var path = tup.basePath; if (!Directory.Exists(path)) { continue; // Is it okay to directly skip it w/o calling noticeFinished? } StatIntermediate statIm; // Check if path is being parsed currently. { criticalPreparationSection.WaitOne(); if (ParseStatistics.TryGetValue(path, out statIm)) { if (tup.finished_untilCount != null) { statIm.parseSubTasksUntilFinished.Add(tup.finished_untilCount); } if (Interlocked.Decrement(ref parsingThreads) < 1) { throw new InvalidOperationException("Race-condition during parse process: There must be two or more parse tasks active!"); } criticalPreparationSection.Set(); continue; } ParseStatistics [path] = statIm = new StatIntermediate { skipFunctionBodies = tup.skipFunctionBodies, basePath = path, }; if (tup.finished_untilCount != null) { statIm.parseSubTasksUntilFinished.Add(tup.finished_untilCount); } criticalPreparationSection.Set(); } // Check if it's necessary to reparse the directory RootPackage oldRoot; if (ParsedDirectories.TryGetValue(path, out oldRoot) && oldRoot.LastParseTime >= Directory.GetLastWriteTimeUtc(path)) { noticeFinish(new ParseIntermediate(statIm, oldRoot, string.Empty)); continue; } statIm.sw.Restart(); //ISSUE: wild card character ? seems to behave differently across platforms // msdn: -> Exactly zero or one character. // monodocs: -> Exactly one character. var files = Directory.GetFiles(path, "*.d", SearchOption.AllDirectories); var ifiles = Directory.GetFiles(path, "*.di", SearchOption.AllDirectories); statIm.totalFiles = statIm.remainingFiles = files.Length + ifiles.Length; var newRoot = new RootPackage { LastParseTime = Directory.GetLastWriteTimeUtc(path) }; if (statIm.totalFiles == 0) { noticeFinish(new ParseIntermediate(statIm, newRoot, string.Empty)); continue; } parseThreadStartEvent.Set(); LaunchParseThreads(); if (files.Length != 0) { foreach (string file in files) { queue.Push(new ParseIntermediate(statIm, newRoot, file)); } } if (ifiles.Length != 0) { foreach (string ifile in ifiles) { queue.Push(new ParseIntermediate(statIm, newRoot, ifile)); } } parseThreadStartEvent.Reset(); } } }
public ParseIntermediate(StatIntermediate im, RootPackage r, string f) { this.im = im; root = r; file = f; }