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; } }
};
}