public static void GetBytes(string url, Action <CacheWebResponse <byte[]> > onBytesDownloaded, Func <string, bool> isRequestCancelled) { BetterThreadPool.QueueUserWorkItem(state => { var response = new CacheWebResponse <byte[]>(); if (!isRequestCancelled(url)) { response.Status = CacheWebResponseStatus.Cancelled; } else { var cachePath = GetCacheFilePath(url); if (_cacheFileIndex.ContainsKey(cachePath)) { try { response.Content = File.ReadAllBytes(cachePath); response.IsCacheHit = true; response.Status = CacheWebResponseStatus.Success; BetterThreadPool.QueueUserWorkItem(notUsed => { InsertOrUpdateCacheEntry(cachePath); }); } catch (IOException ioException) { response.Status = CacheWebResponseStatus.Error; response.ErrorMessage = ioException.Message; } } else { #if !UNITY_WSA || UNITY_EDITOR// We do not have WebClient in Windows Store Apps var client = new TimeoutWebClient(); // set a proxy if one was used if (!string.IsNullOrEmpty(_proxyUrl)) { client.Proxy = new WebProxy(_proxyUrl); } try { response.Content = client.DownloadData(url); response.Status = CacheWebResponseStatus.Success; BetterThreadPool.QueueUserWorkItem( s => { SaveResponseToFileCache(cachePath, response.Content); }); } catch (WebException wex) { response.Status = CacheWebResponseStatus.Error; response.ErrorMessage = wex.ToString(); } #else Debug.LogError("This should not execute."); #endif } } onBytesDownloaded(response); }); }
public static bool InitInstance(int queueSize, int threadNum) { if (Instance != null) { Debug.LogWarning("TreadPool instance is already created."); return(false); } Instance = new BetterThreadPool(queueSize, threadNum); return(true); }
static BetterThreadPool() { Instance = null; }
// Responsible for getting the geometry data for a given request // The method works roughly as follows // 1. Check if model data is in cache // a. If not, start a web request for the data and add this request to the dependency list for the path // 2. If the model data cache indicates that it is being filled (a set value of null) (including if the request // just started during this invocation) add the request to the dependency list for this path // 3. If the model is in the cache and set then get the data for the request and move it forward private IEnumerator GetModelForRequest(LoadCubeRequest loadRequest) { var modelPath = loadRequest.Query.GetModelPath(loadRequest.LodIndex, loadRequest.X, loadRequest.Y, loadRequest.Z, ModelFormatString); while (!Monitor.TryEnter(_geometryBufferCache)) { yield return(null); } // If the geometry data is being loaded or this is the first request to load it add the request the dependency list if (!_geometryBufferCache.ContainsKey(modelPath) || _geometryBufferCache[modelPath] == null) { yield return(StartCoroutine(AddDependentRequest(loadRequest, modelPath))); if (!_geometryBufferCache.ContainsKey(modelPath)) { // Model data was not present in cache nor has any request started constructing it GeometryCacheMisses++; _geometryBufferCache[modelPath] = null; Monitor.Exit(_geometryBufferCache); if (UseWwwForEbo) { var cachePath = CacheWebRequest.GetCacheFilePath(modelPath); WWW modelWww; if (CacheWebRequest.IsItemInCache(cachePath)) { FileCacheHits++; modelWww = new WWW("file:///" + cachePath); yield return(modelWww); } else { FileCacheMisses++; modelWww = new WWW(modelPath); yield return(modelWww); if (modelWww.Succeeded()) { CacheWebRequest.AddToCache(cachePath, modelWww.bytes); } } if (modelWww.Failed()) { Debug.LogError("Error getting model [" + modelPath + "] " + modelWww.error); FailGetGeometryBufferRequest(loadRequest, modelPath); } else { var buffer = new GeometryBuffer(_geometryBufferAltitudeTransform, true) { Buffer = modelWww.bytes, Format = ModelFormat }; BetterThreadPool.QueueUserWorkItem(s => { buffer.Process(); lock (_geometryBufferCache) { _geometryBufferCache[modelPath] = buffer; } SucceedGetGeometryBufferRequest(modelPath, buffer).Wait(); }); } } else { CacheWebRequest.GetBytes(modelPath, modelResponse => { lock (_geometryBufferCache) { if (modelResponse.Status == CacheWebRequest.CacheWebResponseStatus.Error) { Debug.LogError("Error getting model [" + modelPath + "] " + modelResponse.ErrorMessage); FailGetGeometryBufferRequest(loadRequest, modelPath); } else if (modelResponse.Status == CacheWebRequest.CacheWebResponseStatus.Cancelled) { _geometryBufferCache.Remove(modelPath); } else { if (modelResponse.IsCacheHit) { FileCacheHits++; } else { FileCacheMisses++; } var buffer = new GeometryBuffer(_geometryBufferAltitudeTransform, true) { Buffer = modelResponse.Content, Format = ModelFormat }; buffer.Process(); _geometryBufferCache[modelPath] = buffer; SucceedGetGeometryBufferRequest(modelPath, buffer).Wait(); } } }, DependentRequestsExistBlocking); } } else { Monitor.Exit(_geometryBufferCache); } } else // The model data was in the cache { // Model was constructed move request to next step GeometryCacheHits++; loadRequest.GeometryBuffer = _geometryBufferCache[modelPath]; MoveRequestForward(loadRequest); Monitor.Exit(_geometryBufferCache); } }
static CacheWebRequest() { BetterThreadPool.InitInstance(); InitializeCache(DefaultMaxCacheSize); }
public static void AddToCache(string cacheKey, byte[] content) { BetterThreadPool.QueueUserWorkItem(s => { SaveResponseToFileCache(cacheKey, content); }); }