173 lines
4.5 KiB
C#
173 lines
4.5 KiB
C#
using System;
|
|
using ln.logging;
|
|
using System.Threading;
|
|
namespace ln.types.threads
|
|
{
|
|
public delegate void JobDelegate();
|
|
public delegate void ExtendedJobDelegate(PoolJob poolJob);
|
|
|
|
public enum PoolJobState { PREPARED, RUNNING, DONE, FAILED };
|
|
|
|
public class PoolJob
|
|
{
|
|
public string Name { get; set; }
|
|
|
|
public JobDelegate Job { get; }
|
|
public ExtendedJobDelegate ExtendedJob { get; }
|
|
|
|
public double Progress { get; set; }
|
|
public string State { get; set; }
|
|
|
|
public PoolJobState JobState { get; private set; }
|
|
|
|
public bool JobAbortRequested { get; private set; }
|
|
|
|
private Pool Pool { get; set; }
|
|
|
|
protected PoolJob()
|
|
{
|
|
JobState = PoolJobState.PREPARED;
|
|
}
|
|
public PoolJob(JobDelegate job)
|
|
: this()
|
|
{
|
|
Job = job;
|
|
ExtendedJob = null;
|
|
Name = "N/A";
|
|
}
|
|
public PoolJob(ExtendedJobDelegate job)
|
|
: this()
|
|
{
|
|
Job = null;
|
|
ExtendedJob = job;
|
|
Name = "N/A";
|
|
}
|
|
public PoolJob(String name, ExtendedJobDelegate job)
|
|
: this()
|
|
{
|
|
Job = null;
|
|
ExtendedJob = job;
|
|
Name = name;
|
|
}
|
|
|
|
public void RequestAbort()
|
|
{
|
|
JobAbortRequested = true;
|
|
if (Pool != null)
|
|
{
|
|
PoolThread poolThread = Pool.FindPoolThread(this);
|
|
if (poolThread != null)
|
|
{
|
|
if (poolThread.Thread.ThreadState == ThreadState.WaitSleepJoin)
|
|
poolThread.Thread.Interrupt();
|
|
}
|
|
}
|
|
}
|
|
|
|
public void ForceFail()
|
|
{
|
|
JobState = PoolJobState.FAILED;
|
|
}
|
|
public void setState(string state,params object[] p)
|
|
{
|
|
State = String.Format(state, p);
|
|
}
|
|
|
|
|
|
public virtual void RunJob()
|
|
{
|
|
if (Job != null)
|
|
{
|
|
Job();
|
|
}
|
|
else if (ExtendedJob != null)
|
|
{
|
|
ExtendedJob(this);
|
|
}
|
|
else
|
|
{
|
|
Logging.Log(LogLevel.ERROR, "PoolJob without JobDelegate tried to run");
|
|
JobState = PoolJobState.FAILED;
|
|
}
|
|
}
|
|
|
|
public void Run(Pool pool)
|
|
{
|
|
Pool = pool;
|
|
try
|
|
{
|
|
JobState = PoolJobState.RUNNING;
|
|
|
|
RunJob();
|
|
|
|
JobState = PoolJobState.DONE;
|
|
|
|
if (Pool.DEBUG && (State != null) && !String.Empty.Equals(State))
|
|
Logging.Log(LogLevel.DEBUG, "PoolJob exited normally with State={0}", State);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
JobState = PoolJobState.FAILED;
|
|
Logging.Log(LogLevel.ERROR, "PoolJob: {0} caught exception {1}", this, e);
|
|
Logging.Log(e);
|
|
}
|
|
Pool = null;
|
|
}
|
|
|
|
public void SplitJob(PoolJob[] jobs)
|
|
{
|
|
if (Pool == null)
|
|
throw new ArgumentNullException();
|
|
|
|
foreach (PoolJob job in jobs)
|
|
{
|
|
if (!Pool.Enqueue(job))
|
|
{
|
|
Logging.Log(LogLevel.ERROR, "PoolJob.SplitJob(): Failed to enqueue splitted Job");
|
|
foreach (PoolJob _job in jobs)
|
|
{
|
|
_job.RequestAbort();
|
|
}
|
|
throw new Exception("Failed to enqueue splitted Job");
|
|
}
|
|
}
|
|
|
|
while (true)
|
|
{
|
|
int nFinished = 0, nError = 0;
|
|
double progress = 0.0;
|
|
|
|
foreach (PoolJob job in jobs)
|
|
{
|
|
progress += job.Progress;
|
|
|
|
switch (job.JobState)
|
|
{
|
|
case PoolJobState.DONE:
|
|
nFinished++;
|
|
break;
|
|
case PoolJobState.FAILED:
|
|
nError++;
|
|
break;
|
|
}
|
|
|
|
if (JobAbortRequested)
|
|
job.RequestAbort();
|
|
}
|
|
|
|
Progress = progress / jobs.Length;
|
|
|
|
if ((nError + nFinished) == jobs.Length)
|
|
break;
|
|
|
|
Thread.Sleep(1000);
|
|
}
|
|
}
|
|
|
|
public virtual void Prepare()
|
|
{
|
|
}
|
|
|
|
}
|
|
}
|