public void Load(string url, int version, ResolveAction resolve, FallbackAction fallback) { CorgiMemoryChunk chunk = null; if (data.TryGetValue(url, out chunk)) { if (chunk.version >= version) { queue.Remove(chunk.url); queue.AddFirst(chunk.url); resolve(chunk.tex); return; } else { queue.Remove(chunk.url); RemoveChunk(chunk); } } ResolveAction newResolve = (tex) => { Debug.Log("memory new resolved!"); resolve(tex); Save(tex, url, version); }; fallback(url, version, newResolve); }
public void Load(string url, int version, ResolveAction resolve, FallbackAction fallback) { CorgiDiskChunk chunk = null; if (map.TryGetValue(url, out chunk)) { if (chunk.version >= version) { queue.Remove(chunk.url); queue.AddFirst(chunk.url); StartCoroutine(DownloadLocal(chunk, resolve, fallback)); return; } else { queue.Remove(chunk.url); RemoveChunk(chunk); } } ResolveAction newResolve = (tex) => { Save(tex, url, version); resolve(tex); }; fallback(url, version, newResolve); }
IEnumerator DownloadLocal(CorgiDiskChunk chunk, ResolveAction resolve, FallbackAction fallback) { var realPath = Path.Combine(Application.temporaryCachePath, chunk.path); var www = new WWW("file:///" + realPath); Debug.Log("path=" + "file:///" + realPath); yield return(www); if (!string.IsNullOrEmpty(www.error)) { Debug.Log("[ERR]" + www.error + "\n" + chunk.url + " " + chunk.path); RemoveChunk(chunk); fallback(chunk.url, chunk.version, (bytes, tex) => { Save(bytes, chunk.url, chunk.version); resolve(bytes, tex); }); } else { Debug.Log("Disk hit"); Texture2D tex = new Texture2D(0, 0); www.LoadImageIntoTexture(tex); resolve(null, tex); } }
public void Load(string url, int version, ResolveAction resolve, FallbackAction fallback) { CorgiDiskChunk chunk = null; if (chunkData.TryGetValue(url, out chunk)) { if (version >= 0 && chunk.version >= version) { chunkPriorityQueue.Remove(chunk.url); chunkPriorityQueue.AddFirst(chunk.url); corgi.StartCoroutine(DownloadLocal(chunk, resolve, fallback)); return; } else { chunkPriorityQueue.Remove(chunk.url); RemoveChunk(chunk); } } fallback(url, version, (bytes, tex) => { Save(bytes, url, version); resolve(bytes, tex); }); }
public override int ComputeKey() { unchecked { var hashCode = BindingFlags.GetHashCode(); hashCode = (hashCode * 397) ^ (Name != null ? Name.GetHashCode() : 0); hashCode = (hashCode * 397) ^ IsField.GetHashCode(); hashCode = (hashCode * 397) ^ (FallbackAction != null ? FallbackAction.GetHashCode() : 0); hashCode = (hashCode * 397) ^ (GetterFallbackAction != null ? GetterFallbackAction.GetHashCode() : 0); hashCode = (hashCode * 397) ^ (SetterFallbackAction != null ? SetterFallbackAction.GetHashCode() : 0); hashCode = (hashCode * 397) ^ (InterfaceName != null ? InterfaceName.GetHashCode() : 0); hashCode = (hashCode * 397) ^ (FallbackMode != null ? FallbackMode.GetHashCode() : 0); return(hashCode); } }
private static async Task ExecuteAsync <TResult>( this ActionContext <TResult>[] actionCtxBatch, FallbackAction <TResult> fallbackAction) { try { await fallbackAction(actionCtxBatch); } catch (Exception ex) { foreach (var actionCtx in actionCtxBatch) { actionCtx.TaskCompletionSource.TrySetException(ex); } } }
public void Load(string url, int version, ResolveAction resolve, FallbackAction fallback) { CorgiMemoryChunk chunk = null; if (chunkData.TryGetValue(url, out chunk)) { // 아래 레이어에서 로드중인데 계속 요청이 들어오면 해당 key resolveQueue에 저장했다가 완료시 한꺼번에 호출 if (chunk == null) { Debug.Log("fetch pending.. " + url + " v." + version); ResolveAction delegates; if (resolveQueues.TryGetValue(url, out delegates)) { delegates += resolve; } else { resolveQueues.Add(url, resolve); } return; } else if (version >= 0 && chunk.version >= version) { chunkPriorityQueue.Remove(chunk.url); chunkPriorityQueue.AddFirst(chunk.url); resolve(null, chunk.tex); return; } else { chunkPriorityQueue.Remove(chunk.url); RemoveChunk(chunk); } } //아래 레이어에서 로드중인경우 체크용으로 해당 key chunk에 null을 넣어둔다. chunkData.Add(url, null); fallback(url, version, (bytes, tex) => { resolve(bytes, tex); OnResolve(url, version, tex); }); }
IEnumerator DownloadURL(string url, int version, ResolveAction resolve, FallbackAction fallback) { var www = new WWW(url); yield return(www); if (string.IsNullOrEmpty(www.error)) { Debug.Log("Web hit"); Texture2D tex = new Texture2D(0, 0); www.LoadImageIntoTexture(tex); resolve(www.bytes, tex); } else { Debug.Log("Web Failed!"); fallback(url, version, resolve); } }
internal static async Task ImplementationAsync <TResult>( SemaphoreSlim maxParallelizationSemaphore, int[] maxQueueingActionsLimits, ConcurrentQueue <ActionContext <TResult> > queuedActions, FallbackAction <TResult> fallbackAction) { do { if (!maxParallelizationSemaphore.Wait(0)) { return; } await Task .Run(() => queuedActions.ExecuteAsync(maxQueueingActionsLimits, fallbackAction)) .ConfigureAwait(false); maxParallelizationSemaphore.Release(); // This extra check is needed to prevent the possible race-condition where an action has // been enqueued in an empty queue while the Semaphore is being released, leading to a // situation where the last action is stuck in the queue until a new action is enqueued. } while (!queuedActions.IsEmpty); }
private static async Task ExecuteAsync <TResult>( this ConcurrentQueue <ActionContext <TResult> > queuedActions, int[] maxQueueingActionsLimits, FallbackAction <TResult> fallbackAction) { while (true) { var actionCtxBatch = default(ActionContext <TResult>[]); var actionCtx = default(ActionContext <TResult>); lock (queuedActions) { var exceededLimits = maxQueueingActionsLimits.Where(x => x <= queuedActions.Count); if (exceededLimits.Any()) { actionCtxBatch = queuedActions.Dequeue(exceededLimits.First()); } else if (queuedActions.TryDequeue(out actionCtx)) { } else { break; } } if (actionCtxBatch != null) { await actionCtxBatch.ExecuteAsync(fallbackAction); } else { await actionCtx.ExecuteAsync(); } } }
void _Fallback(FallbackAction _fallback) { EnsureMainthread(); _fallback += _fallback; }
/// <summary> /// Builds a bulkhead isolation <see cref="AsyncPolicy{TResult}" />, which limits the maximum concurrency of actions executed through the policy. Imposing a maximum concurrency limits the potential of governed actions, when faulting, to bring down the system. /// <para>When an execution would cause the number of actions executing concurrently through the policy to exceed <paramref name="maxParallelization" /> they will be queued and executed in-order. When an execution would cause the number of queuing actions to exceed any of the <paramref name="maxQueuingActionsLimits" />, <paramref name="fallbackActionAsync" /> is called with a number of <see cref="ActionContext{TResult}" /> equal to the largest exceeded limit in <paramref name="maxQueuingActionsLimits" />.</para> /// </summary> /// <param name="maxParallelization">The maximum number of concurrent actions that may be executing through the policy.</param> /// <param name="maxQueuingActionsLimits">The maxmimum number of actions that may be queuing, waiting for an execution slot.</param> /// <param name="fallbackActionAsync">An action to call asynchronously, if the bulkhead rejects execution due to oversubscription.</param> /// <returns>The policy instance.</returns> /// <exception cref="System.ArgumentOutOfRangeException">maxParallelization;Value must be greater than zero.</exception> /// <exception cref="System.ArgumentOutOfRangeException">maxQueuingActionsLimits;Value must be greater than or equal to zero.</exception> /// <exception cref="System.ArgumentNullException">fallbackActionAsync</exception> public static AsyncFallbackBulkheadPolicy <TResult> Create <TResult>(int maxParallelization, FallbackAction <TResult> fallbackActionAsync, params int[] maxQueuingActionsLimits) { if (maxParallelization <= 0) { throw new ArgumentOutOfRangeException(nameof(maxParallelization), "Value must be greater than zero."); } if (maxQueuingActionsLimits.Any(x => x <= 0)) { throw new ArgumentOutOfRangeException(nameof(maxQueuingActionsLimits), "Value must be greater than zero."); } if (fallbackActionAsync == null) { throw new ArgumentNullException(nameof(fallbackActionAsync)); } return(new AsyncFallbackBulkheadPolicy <TResult>( maxParallelization, fallbackActionAsync, maxQueuingActionsLimits )); }
void _Fallback(FallbackAction _fallback) { fallbackDelegate = _fallback; }
/* * public static void AddCacheLayer(int priority, FallbackAction action) * { * instance._AddCacheLayer(priority, action); * } * * void _AddCacheLayer(int priority, FallbackAction action) * { * } */ public static void Fallback(FallbackAction fallback) { instance._Fallback(fallback); }
private void RunCall(IDataContainer obj, string func, object[] parameters, bool isSelf, FallbackAction fallback) { // This executes in the job thread. // Checks if this is still alive. if (IsDisposed) { return; } // Checks if the function still exists. LuaDataContainer dc = obj as LuaDataContainer; if (dc == null) { return; } IDataProvider lf = dc.GetProvider(func, isSelf); if (lf == null) { return; } // Calls the function. try { lf.Execute(parameters); } catch (InvalidOperationException ex) { // Last chance fallback action, if any. if (fallback != null) { fallback(ex); } else if (DefaultFallbackAction != null) { DefaultFallbackAction(ex); } else { // No fallback action: let's rethrow this. throw; } } catch (Exception) { // Other exceptions than InvalidOperationException are // immediately rethrown because they are, indeed, unexpected. throw; } }
private Action GetJob(IDataContainer obj, string func, object[] parameters, bool isSelf, FallbackAction fallbackAction) { return(new Action(() => RunCall(obj, func, parameters, isSelf, fallbackAction))); }
/// <summary> /// Executes asynchronously a call to a Lua self-function on the thread this ExecutionQueue is associated with. /// </summary> /// <remarks>This method returns once the call job is queued.</remarks> /// <param name="obj">IDataContainer that contains the self-function.</param> /// <param name="func">Field name in <paramref name="obj"/> that corresponds to the function to call.</param> /// <param name="fallback">Action that is executed if an exception occurs during the /// execution of the job. If this parameter is null, any exception occuring will be /// rethrown.</param> /// <param name="parameters">Optional parameters to pass to the function. <paramref name="obj"/> is automatically /// added as first parameter.</param> public void BeginCallSelf(IDataContainer obj, string func, FallbackAction fallback, params object[] parameters) { // Conforms the parameters and enqueues a job. AcceptJob(GetJob(obj, func, ConformParameters(parameters), true, fallback)); }
private void RunCall(IDataContainer obj, string func, object[] parameters, bool isSelf, FallbackAction fallback) { // This executes in the job thread. // Checks if this is still alive. if (IsDisposed) return; // Checks if the function still exists. LuaDataContainer dc = obj as LuaDataContainer; if (dc == null) return; IDataProvider lf = dc.GetProvider(func, isSelf); if (lf == null) return; // Calls the function. try { lf.Execute(parameters); } catch (InvalidOperationException ex) { // Last chance fallback action, if any. if (fallback != null) { fallback(ex); } else if (DefaultFallbackAction != null) { DefaultFallbackAction(ex); } else { // No fallback action: let's rethrow this. throw; } } catch (Exception) { // Other exceptions than InvalidOperationException are // immediately rethrown because they are, indeed, unexpected. throw; } }
private Action GetJob(IDataContainer obj, string func, object[] parameters, bool isSelf, FallbackAction fallbackAction) { return new Action(() => RunCall(obj, func, parameters, isSelf, fallbackAction)); }
/// <summary> /// Builds a bulkhead isolation <see cref="AsyncPolicy{TResult}" />, which limits the maximum concurrency of actions executed through the policy. Imposing a maximum concurrency limits the potential of governed actions, when faulting, to bring down the system. /// <para>When an execution would cause the number of actions executing concurrently through the policy to exceed <paramref name="maxParallelization" /> they will be queued and executed in-order.</para> /// </summary> /// <param name="maxParallelization">The maximum number of concurrent actions that may be executing through the policy.</param> /// <returns>The policy instance.</returns> public static AsyncFallbackBulkheadPolicy <TResult> Create <TResult>(int maxParallelization) { FallbackAction <TResult> doNothingAsync = _ => TaskHelper.EmptyTask; return(Create(maxParallelization, doNothingAsync)); }
public void Load(string url, int version, ResolveAction resolve, FallbackAction fallback) { corgi.StartCoroutine(DownloadURL(url, version, resolve, fallback)); }