<commit_before>{ceil, round} = Math
{
  defineModule, inspect, min, max, bound, log, createWithPostCreate, isString, isNumber, isPlainArray, timeout
  Promise
} = require 'art-standard-lib'
{BaseClass} = require 'art-class-system'
{point, rect, Matrix, point0, point1} = require 'art-atomic'
{isImage, Bitmap, BitmapBase} = require 'art-canvas'
ShadowableElement = require '../ShadowableElement'

defineModule module, class BitmapElement extends ShadowableElement

  class BitmapElement.SourceToBitmapCache extends BaseClass
    @singletonClass()

    constructor: ->
      @_cache = {}
      @_referenceCounts = {}
      @_loaded = {}

    # OUT: promise.then (bitmap) ->
    get: (url, initializerPromise) ->
      return Bitmap.get url unless isString url # non-string sources are not cached
      @_referenceCounts[url] = (@_referenceCounts[url] || 0) + 1
      out = @_cache[url] ||= initializerPromise || Bitmap.get url
      out.then (bitmap) => @_loaded[url] = bitmap
      out

    loaded: (url) -> @_loaded[url]

    temporaryPut: (duration, url, bitmap) ->
      @get url, Promise.resolve bitmap
      # log temporaryPut: {bitmap, duration, url}
      timeout duration, =>
        # log temporaryPut: release: {bitmap, url}
        @release url<commit_msg>IMPROVED - image-load failures get automatic, exponential fall-off retrys as long as they are requested<commit_after>{ceil, round} = Math
{
  defineModule, inspect, min, max, bound, log, createWithPostCreate, isString, isNumber, isPlainArray, timeout
  Promise
} = require 'art-standard-lib'
{BaseClass} = require 'art-class-system'
{point, rect, Matrix, point0, point1} = require 'art-atomic'
{isImage, Bitmap, BitmapBase} = require 'art-canvas'
ShadowableElement = require '../ShadowableElement'

defineModule module, class BitmapElement extends ShadowableElement

  class BitmapElement.SourceToBitmapCache extends BaseClass
    @singletonClass()

    constructor: ->
      @_cache = {}
      @_referenceCounts = {}
      @_loaded = {}

    # OUT: promise.then (bitmap) ->
    get: (url, initializerPromise) ->
      return Bitmap.get url unless isString url # non-string sources are not cached
      @_referenceCounts[url] = (@_referenceCounts[url] || 0) + 1
      @_cache[url] ||= initializerPromise || @_get url
      .tap (bitmap) => @_loaded[url] = bitmap

    _get: (url, tryCount = 0) ->
      Bitmap.get url
      # .tap =>
      #   if tryCount > 0
      #     log sourceToBitmapCacheSuccess: {url, tryCount, refs: @_referenceCounts[url]}
      .catch (error) =>
        if @_referenceCounts[url] > 0
          retryInSeconds = min(30, (2 ** tryCount)) * .9 + .2 * Math.random()
          # log sourceToBitmapCache1: {retryInSeconds, url, tryCount, refs: @_referenceCounts[url], message: error?.message}
          timeout 1000 * retryInSeconds, =>
            # log sourceToBitmapCache2: {retryInSeconds, url, tryCount, refs: @_referenceCounts[url]}
            if @_referenceCounts[url] > 0
              @_get url, tryCount + 1
            else throw error
        else throw error

    loaded: (url) -> @_loaded[url]

    temporaryPut: (duration, url, bitmap) ->
      @get url, Promise.resolve bitmap
      # log temporaryPut: {bitmap, duration, url}
      timeout duration, =>
        # log temporaryPut: release: {bitmap, url}
        @release url
{'fraction_non_alphanumeric': 0.1203842689882918, 'fraction_numerical': 0.00720504353047133, 'mean_word_length': 3.2445859872611464, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 24, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5932268', 'n_tokens_mistral': 1018, 'n_tokens_neox': 991, 'n_words': 282}