您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
145 行
4.3 KiB
145 行
4.3 KiB
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using UnityEngine;
|
|
|
|
namespace UnityEditor.Experimental.ShaderTools.Internal
|
|
{
|
|
public class ProcessManager
|
|
{
|
|
public interface IProcess
|
|
{
|
|
ProcessStartInfo startInfo { get; }
|
|
Process process { get; }
|
|
bool hasStarted { get; }
|
|
}
|
|
|
|
class ProcessImpl : IProcess
|
|
{
|
|
Action<IProcess> m_PreStart;
|
|
Action<IProcess> m_PostStart;
|
|
|
|
public ProcessStartInfo startInfo { get; private set; }
|
|
public Process process { get; private set; }
|
|
public bool hasStarted { get { return process != null; } }
|
|
|
|
public ProcessImpl(ProcessStartInfo startInfo, Action<IProcess> preStart, Action<IProcess> postStart)
|
|
{
|
|
this.startInfo = startInfo;
|
|
m_PreStart = preStart;
|
|
m_PostStart = postStart;
|
|
}
|
|
|
|
public void Start()
|
|
{
|
|
process = new Process();
|
|
process.StartInfo = startInfo;
|
|
process.EnableRaisingEvents = true;
|
|
|
|
if (m_PreStart != null)
|
|
m_PreStart(this);
|
|
|
|
process.Start();
|
|
|
|
if (m_PostStart != null)
|
|
m_PostStart(this);
|
|
}
|
|
|
|
public void Cancel()
|
|
{
|
|
if (process != null && !process.HasExited)
|
|
process.Kill();
|
|
}
|
|
}
|
|
|
|
const int k_MaxProcesses = 16;
|
|
|
|
static ProcessManager s_Instance = new ProcessManager(k_MaxProcesses);
|
|
|
|
int m_UpdateRefCount = 0;
|
|
int m_MaxProcesses;
|
|
List<ProcessImpl> m_PendingProcesses = new List<ProcessImpl>();
|
|
List<ProcessImpl> m_RunningProcesses = new List<ProcessImpl>();
|
|
|
|
public static IProcess Enqueue(ProcessStartInfo startInfo, Action<IProcess> preStart, Action<IProcess> postStart)
|
|
{
|
|
return s_Instance.DoEnqueue(startInfo, preStart, postStart);
|
|
}
|
|
|
|
public static void Cancel(IProcess process)
|
|
{
|
|
s_Instance.DoCancel(process);
|
|
}
|
|
|
|
public ProcessManager(int maxProcesses)
|
|
{
|
|
m_MaxProcesses = maxProcesses;
|
|
}
|
|
|
|
IProcess DoEnqueue(ProcessStartInfo startInfo, Action<IProcess> preStart, Action<IProcess> postStart)
|
|
{
|
|
var impl = new ProcessImpl(startInfo, preStart, postStart);
|
|
m_PendingProcesses.Add(impl);
|
|
|
|
if (m_UpdateRefCount == 0)
|
|
EditorApplication.update += Update;
|
|
|
|
++m_UpdateRefCount;
|
|
|
|
return impl;
|
|
}
|
|
|
|
void DoCancel(IProcess process)
|
|
{
|
|
var processImpl = (ProcessImpl)process;
|
|
var pendingIndex = m_PendingProcesses.IndexOf(processImpl);
|
|
if (pendingIndex != -1)
|
|
{
|
|
m_PendingProcesses.RemoveAt(pendingIndex);
|
|
return;
|
|
}
|
|
|
|
var runningIndex = m_RunningProcesses.IndexOf(processImpl);
|
|
if (runningIndex != -1)
|
|
{
|
|
m_RunningProcesses.RemoveAt(runningIndex);
|
|
processImpl.Cancel();
|
|
}
|
|
}
|
|
|
|
void Update()
|
|
{
|
|
for (var i = m_RunningProcesses.Count - 1; i >= 0 ; --i)
|
|
{
|
|
var proc = m_RunningProcesses[i];
|
|
if (proc.process.HasExited)
|
|
{
|
|
m_RunningProcesses.RemoveAt(i);
|
|
|
|
--m_UpdateRefCount;
|
|
if (m_UpdateRefCount == 0)
|
|
EditorApplication.update -= Update;
|
|
}
|
|
}
|
|
|
|
var processToRun = Mathf.Min(m_MaxProcesses, m_PendingProcesses.Count - m_RunningProcesses.Count);
|
|
for (var i = 0; i < processToRun; i++)
|
|
{
|
|
var proc = m_PendingProcesses[0];
|
|
m_PendingProcesses.RemoveAt(0);
|
|
|
|
proc.Start();
|
|
m_RunningProcesses.Add(proc);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static class ProcessManagerExtensions
|
|
{
|
|
public static bool IsComplete(this ProcessManager.IProcess process)
|
|
{
|
|
return process != null && process.process != null && process.hasStarted && process.process.HasExited;
|
|
}
|
|
}
|
|
}
|