private async Task DoJob() { long now = SystemClock.UptimeMillis; EncodedImage input; bool isLast; lock (_gate) { input = _encodedImage; isLast = _isLast; _encodedImage = null; _isLast = false; _jobState = JobState.RUNNING; _jobStartTime = now; } try { // we need to do a check in case the job got cleared in the meantime if (ShouldProcess(input, isLast)) { await _jobRunnable.Invoke(input, isLast).ConfigureAwait(false); } } finally { EncodedImage.CloseSafely(input); OnJobFinished(); } }
public void TestCloseSafely() { EncodedImage encodedImage = new EncodedImage(_byteBufferRef); EncodedImage.CloseSafely(encodedImage); Assert.AreEqual(1, _byteBufferRef.GetUnderlyingReferenceTestOnly().GetRefCountTestOnly()); }
/// <summary> /// Performs the decode synchronously. /// </summary> private async Task DoDecode(EncodedImage encodedImage, bool isLast) { if (IsFinished() || !EncodedImage.IsValid(encodedImage)) { return; } try { long queueTime = _jobScheduler.GetQueuedTime(); int length = isLast ? encodedImage.Size : GetIntermediateImageEndOffset(encodedImage); if (length == 0) { return; } IQualityInfo quality = isLast ? ImmutableQualityInfo.FULL_QUALITY : GetQualityInfo(); _producerListener.OnProducerStart(_producerContext.Id, PRODUCER_NAME); CloseableImage image = null; try { image = await _parent._imageDecoder .DecodeImageAsync(encodedImage, length, quality, _imageDecodeOptions) .ConfigureAwait(false); } catch (Exception e) { _producerListener.OnProducerFinishWithFailure( _producerContext.Id, PRODUCER_NAME, e, GetExtraMap(image, queueTime, quality, isLast)); HandleError(e); return; } _producerListener.OnProducerFinishWithSuccess( _producerContext.Id, PRODUCER_NAME, GetExtraMap(image, queueTime, quality, isLast)); HandleResult(image, isLast); } finally { EncodedImage.CloseSafely(encodedImage); } }
/// <summary> /// Clears the currently set job. /// /// <para /> In case the currently set job has been scheduled but /// not started yet, the job won't be executed. /// </summary> public void ClearJob() { EncodedImage oldEncodedImage; lock (_gate) { oldEncodedImage = _encodedImage; _encodedImage = null; _isLast = false; } EncodedImage.CloseSafely(oldEncodedImage); }
/// <summary> /// Associates encodedImage with given key in disk cache. /// Disk write is performed on background thread, so the /// caller of this method is not blocked. /// </summary> public Task Put(ICacheKey key, EncodedImage encodedImage) { Preconditions.CheckNotNull(key); Preconditions.CheckArgument(EncodedImage.IsValid(encodedImage)); // Store encodedImage in staging area _stagingArea.Put(key, encodedImage); // Write to disk cache. This will be executed on background thread, // so increment the ref count. When this write completes // (with success/failure), then we will bump down the ref count again. EncodedImage finalEncodedImage = EncodedImage.CloneOrNull(encodedImage); try { Task writeTask = _writeExecutor.Execute(() => { try { WriteToDiskCache(key, finalEncodedImage); } finally { _stagingArea.Remove(key, finalEncodedImage); EncodedImage.CloseSafely(finalEncodedImage); // Removes write task after it's completed. Task writeTaskCompleted = default(Task); _writeToDiskCacheTasks.TryRemove(key, out writeTaskCompleted); } }); _writeToDiskCacheTasks.TryAdd(key, writeTask); return(writeTask); } catch (Exception) { // We failed to enqueue cache write. Log failure and decrement ref count // TODO: 3697790 Debug.WriteLine($"Failed to schedule disk-cache write for { key.ToString() }"); _stagingArea.Remove(key, encodedImage); EncodedImage.CloseSafely(finalEncodedImage); // Removes write task due to error. Task writeTaskCompleted = default(Task); _writeToDiskCacheTasks.TryRemove(key, out writeTaskCompleted); throw; } }
/// <summary> /// Updates the job. /// /// <para />This just updates the job, but it doesn't schedule it. /// In order to be executed, the job has to be scheduled after /// being set. In case there was a previous job scheduled that has /// not yet started, this new job will be executed instead. /// </summary> /// <returns> /// Whether the job was successfully updated. /// </returns> public bool UpdateJob(EncodedImage encodedImage, bool isLast) { if (!ShouldProcess(encodedImage, isLast)) { return(false); } EncodedImage oldEncodedImage; lock (_gate) { oldEncodedImage = _encodedImage; _encodedImage = EncodedImage.CloneOrNull(encodedImage); _isLast = isLast; } EncodedImage.CloseSafely(oldEncodedImage); return(true); }
/// <summary> /// Removes key-value from the StagingArea. Both key and value must match. /// </summary> /// <param name="key">The cache key.</param> /// <param name="encodedImage">Value corresponding to key.</param> /// <returns>true if item was removed.</returns> public bool Remove(ICacheKey key, EncodedImage encodedImage) { lock (_mapGate) { Preconditions.CheckNotNull(key); Preconditions.CheckNotNull(encodedImage); Preconditions.CheckArgument(EncodedImage.IsValid(encodedImage)); EncodedImage oldValue = default(EncodedImage); if (!_map.TryGetValue(key, out oldValue)) { return(false); } CloseableReference <IPooledByteBuffer> oldReference = oldValue.GetByteBufferRef(); CloseableReference <IPooledByteBuffer> reference = encodedImage.GetByteBufferRef(); try { if (oldReference == null || reference == null || oldReference.Get() != reference.Get()) { return(false); } _map.Remove(key); } finally { CloseableReference <IPooledByteBuffer> .CloseSafely(reference); CloseableReference <IPooledByteBuffer> .CloseSafely(oldReference); EncodedImage.CloseSafely(oldValue); } #if DEBUG_STAGING_AREA LogStats(); #endif // DEBUG_STAGING_AREA return(true); } }
/// <summary> /// Stores key-value in this StagingArea. /// </summary> /// <param name="key">The cache key.</param> /// <param name="encodedImage"> /// EncodedImage to be associated with key. /// </param> public void Put(ICacheKey key, EncodedImage encodedImage) { lock (_mapGate) { Preconditions.CheckNotNull(key); Preconditions.CheckArgument(EncodedImage.IsValid(encodedImage)); // We're making a 'copy' of this reference - so duplicate it EncodedImage oldEntry = default(EncodedImage); if (_map.TryGetValue(key, out oldEntry)) { _map.Remove(key); } _map.Add(key, EncodedImage.CloneOrNull(encodedImage)); EncodedImage.CloseSafely(oldEntry); #if DEBUG_STAGING_AREA LogStats(); #endif // DEBUG_STAGING_AREA } }