using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; using glue.Tasks; using glue.Debugging; namespace agree.Parse { /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public class ParseException : Exception { static int next_id = 0; public ParseException(String fmt, params Object[] args) : base(fmt == null ? String.Empty : String.Format(fmt, args)) { id = Interlocked.Increment(ref next_id); } protected ParseException() : this(null) { } readonly int id; public int Id { get { return id; } } }; public class ParseTimeoutException : ParseException { public ParseTimeoutException() { } public ParseTimeoutException(String fmt, params Object[] args) : base(String.Format(fmt, args)) { } }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// /// coordination of asynchronous chart tasks: creation and cancellation /// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// abstract public class TaskCancellationChart<T> : ChartBase<T> where T : ChartBase<T>.IMotherDaughter, IEquatable<T> { internal TaskCancellationChart(ParserConfiguration config, ISysObj so_owner, String source_text, int c_cols) : base(config, so_owner, source_text, c_cols) { cancel_tok_src = new CancellationTokenSource(); tf = new TaskFactory( cancel_tok_src.Token, TaskCreationOptions.AttachedToParent, TaskContinuationOptions.AttachedToParent, TaskScheduler.Default); } readonly protected Stopwatch timer = new Stopwatch(); readonly CancellationTokenSource cancel_tok_src; readonly TaskFactory tf; public TimeSpan ParseTime { get { return timer.Elapsed; } } int c_tasks = 0; static public int c_tasks_max = int.MaxValue; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// internal Task StartAttachedChildTask(Action a) { if (c_tasks_max == int.MaxValue) return tf.StartNew(a); if (c_tasks > c_tasks_max) { try { a(); } catch (Exception) { throw; } return Tasks.CompletedTask; } Interlocked.Increment(ref c_tasks); return tf.StartNew(() => { a(); Interlocked.Decrement(ref c_tasks); }); } #if false internal Task<X> StartAttachedChildTask<X>(Func<X> f) { if (Nop.single_threaded) { X x = default(X); try { x = f(); } catch (Exception) { throw; } return Tasks.FromResult(x); } else { return tf.StartNew<X>(f); } } #endif internal Task StartAttachedChildTask<X>(Action<X> ax, X x) { if (c_tasks_max == int.MaxValue) return tf.StartNew(() => ax(x)); if (c_tasks > c_tasks_max) { try { ax(x); } catch (Exception) { throw; } return Tasks.CompletedTask; } Interlocked.Increment(ref c_tasks); return tf.StartNew(() => { ax(x); Interlocked.Decrement(ref c_tasks); }); } protected void CancelParse() { cancel_tok_src.Cancel(false); } protected CancellationToken CancelTok { get { return cancel_tok_src.Token; } } protected TaskFactory TaskFactory { get { return tf; } } }; }