using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEditor.Build.Pipeline.Interfaces; using UnityEngine; namespace UnityEditor.Build.Pipeline.Utilities { internal static class TaskCachingUtility { public class WorkItem { public T Context; public int Index; public CacheEntry entry; public string StatusText; public WorkItem(T context, string statusText = "") { this.Context = context; this.StatusText = statusText; } } public interface IRunCachedCallbacks { /// /// Creates a cache entry for the specified work item. /// /// The work item. /// Returns the created entry. CacheEntry CreateCacheEntry(WorkItem item); /// /// Process the uncached work item. /// /// The work item. void ProcessUncached(WorkItem item); /// /// Process the cached work item. /// /// The work item. /// The cached information for the work item. void ProcessCached(WorkItem item, CachedInfo info); /// /// Post processes the work item. /// /// The work item. void PostProcess(WorkItem item); /// /// Creates cached information for the specified work item. /// /// The work item. /// Returns the cached information created. CachedInfo CreateCachedInfo(WorkItem item); } public static ReturnCode RunCachedOperation(IBuildCache cache, IBuildLogger log, IProgressTracker tracker, List> workItems, IRunCachedCallbacks cbs ) { using (log.ScopedStep(LogLevel.Info, "RunCachedOperation")) { List cacheEntries = null; List> nonCachedItems = workItems; var cachedItems = new List>(); for (int i = 0; i < workItems.Count; i++) { workItems[i].Index = i; } IList cachedInfo = null; if (cache != null) { using (log.ScopedStep(LogLevel.Info, "Creating Cache Entries")) for (int i = 0; i < workItems.Count; i++) { workItems[i].entry = cbs.CreateCacheEntry(workItems[i]); } cacheEntries = workItems.Select(i => i.entry).ToList(); using (log.ScopedStep(LogLevel.Info, "Load Cached Data")) cache.LoadCachedData(cacheEntries, out cachedInfo); cachedItems = workItems.Where(x => cachedInfo[x.Index] != null).ToList(); nonCachedItems = workItems.Where(x => cachedInfo[x.Index] == null).ToList(); } using (log.ScopedStep(LogLevel.Info, "Process Entries")) foreach (WorkItem item in nonCachedItems) { if (!tracker.UpdateInfoUnchecked(item.StatusText)) return ReturnCode.Canceled; cbs.ProcessUncached(item); } using (log.ScopedStep(LogLevel.Info, "Process Cached Entries")) foreach (WorkItem item in cachedItems) cbs.ProcessCached(item, cachedInfo[item.Index]); foreach (WorkItem item in workItems) cbs.PostProcess(item); if (cache != null) { List uncachedInfo; using (log.ScopedStep(LogLevel.Info, "Saving to Cache")) { using (log.ScopedStep(LogLevel.Info, "Creating Cached Infos")) uncachedInfo = nonCachedItems.Select((item) => cbs.CreateCachedInfo(item)).ToList(); cache.SaveCachedData(uncachedInfo); } } log.AddEntrySafe(LogLevel.Info, $"Total Entries: {workItems.Count}, Processed: {nonCachedItems.Count}, Cached: {cachedItems.Count}"); return ReturnCode.Success; } } } }