using System; using System.Collections; using System.Collections.Generic; using System.Threading; using UnityEngine; namespace Cute; public class LeanThreadPool { private static LeanThreadPool _instance; private Thread[] _threads; private Semaphore _semaphore; private object _jobsLock; private object _convergeLock; private List _jobs; private bool _quit; private int _convergeCount; public static LeanThreadPool Instance { get { if (_instance == null) { _instance = new LeanThreadPool(); } return _instance; } } public int ThreadsCount => _threads.Length; private LeanThreadPool() { int processorCount = SystemInfo.processorCount; _jobs = new List(); _jobsLock = new object(); _convergeLock = new object(); _semaphore = new Semaphore(0, int.MaxValue); _threads = new Thread[processorCount]; for (int i = 0; i < _threads.Length; i++) { _threads[i] = new Thread(ThreadFunction); _threads[i].Start(); } } private void ThreadFunction() { ParallelJob parallelJob = null; while (!_quit) { _semaphore.WaitOne(); lock (_jobsLock) { if (_jobs.Count > 0) { parallelJob = _jobs[0]; _jobs.Remove(parallelJob); } } if (parallelJob != null) { parallelJob.Run(); parallelJob = null; } } lock (_convergeLock) { _convergeCount++; } } public IEnumerator KillAll(Action callback = null) { _quit = true; _convergeCount = 0; lock (_jobsLock) { _jobs.Clear(); } _semaphore.Release(_threads.Length); while (_convergeCount < _threads.Length) { yield return 0; } callback.Call(); } public void AddJob(ParallelJob job) { lock (_jobsLock) { _jobs.Add(job); } _semaphore.Release(); } }