Class: Weak::Cache

Inherits:
Object
  • Object
show all
Defined in:
lib/weak/cache.rb

Overview

Weak::Cache provides a thread-safe wrapper around Map to provide an object cache. As with a Map, keys and values are both weakly referenced so that a stored key-value pair vanishes if either the key or the value is garbage-collected.

We implement an interface similar to that of ActiveSupport::Cache::Store.

Instance Method Summary collapse

Constructor Details

#initializeCache

Returns a new empty Weak::Cache object



20
21
22
23
# File 'lib/weak/cache.rb', line 20

def initialize
  @map = Map.new
  @mutex = Mutex.new
end

Instance Method Details

#clearself

Clears the entire cache.

Returns:

  • (self)


28
29
30
31
# File 'lib/weak/cache.rb', line 28

def clear
  @mutex.synchronize { @map.clear }
  self
end

#clone(freeze: false) ⇒ Weak::Cache

Weak::Cache objects can't be frozen since this is not enforced by the underlying Map, resp. its ObjectSpace::WeakMap implementation. Thus, we try to signal this by not actually setting the frozen? flag and ignoring attempts to freeze us with just a warning.

Parameters:

  • freeze (Bool, nil) (defaults to: false)

    ignored; we always behave as if this is false. If this is set to a truethy value, we emit a warning.

Returns:

  • (Weak::Cache)

    a new Weak::Cache object containing the same elements as self



42
43
44
45
# File 'lib/weak/cache.rb', line 42

def clone(freeze: false)
  warn("Can't freeze #{self.class}") if freeze
  @mutex.synchronize { super(freeze: false) }
end

#delete(key) ⇒ Bool

Note:

Map does not test member equality with == or eql?. Instead, it always checks strict object equality, so that, e.g., different String keys are not considered equal, even if they may contain the same content.

Deletes an entry in the cache. Returns true if an entry was deleted, false otherwise.

Parameters:

  • key (Object)

    the key to delete

Returns:

  • (Bool)

    true if the entry was deleted, false otherwise



53
54
55
56
57
58
59
60
# File 'lib/weak/cache.rb', line 53

def delete(key)
  @mutex.synchronize {
    @map.delete(key) do
      return false
    end
    true
  }
end

#dupWeak::Cache

Returns a new Weak::Cache object containing the same elements as self.

Returns:

  • (Weak::Cache)

    a new Weak::Cache object containing the same elements as self



64
65
66
# File 'lib/weak/cache.rb', line 64

def dup
  @mutex.synchronize { super }
end

#each_key {|key| ... } ⇒ self, Enumerator

Calls the given block once for each live key in self, passing the key as a parameter. Returns the weak map itself.

If no block is given, an Enumerator is returned instead.

Yields:

  • (key)

    calls the given block once for each key in self

Yield Parameters:

  • key (Object)

    the key of the current key-value pair

Returns:

  • (self, Enumerator)

    self if a block was given or an Enumerator if no block was given.



69
70
71
72
73
# File 'lib/weak/cache.rb', line 69

def each_key(&block)
  return enum_for(__method__) { size } unless block_given?
  keys.each(&block)
  self
end

#empty?Boolean

Returns true if self contains no elements.

Returns:

  • (Boolean)

    true if self contains no elements



76
77
78
# File 'lib/weak/cache.rb', line 76

def empty?
  @mutex.synchronize { @map.empty? }
end

#exist?(key) ⇒ Bool Also known as: include?, key?

Note:

Map does not test member equality with == or eql?. Instead, it always checks strict object equality, so that, e.g., different String keys are not considered equal, even if they may contain the same content.

Returns true if the given key is included in self and has an associated live value, false otherwise.

Parameters:

  • key (Object)

    a possible key

Returns:

  • (Bool)

    true if the given key is included in self and has an associated live value, false otherwise



81
82
83
# File 'lib/weak/cache.rb', line 81

def exist?(key)
  @mutex.synchronize { @map.include?(key) }
end

#fetch(key, skip_nil: false) {|key| ... } ⇒ Object

Note:

Map does not test member equality with == or eql?. Instead, it always checks strict object equality, so that, e.g., different String keys are not considered equal, even if they may contain the same content.

Fetches or sets data from the cache, using the given key. If there is a value in the cache for the given key, that value is returned.

If there is no value in the cache (a cache miss), then the given block will be passed the key and executed in the event of a cache miss. The return value of the block will be written to the cache under the given cache key, and that return value will be returned.

Parameters:

  • key (Object)

    the key for the requested value

  • skip_nil (Bool) (defaults to: false)

    prevents caching a nil value from the block

Yields:

  • (key)

    if no value was set at key, we call the block, write its returned value for the key in the cache and return the value

Yield Parameters:

  • key (String)

    the given key

Returns:

  • (Object)

    the value for the given key if present in the cache. If the key was not found, we return the value of the given block.

Raises:

  • (ArgumentError)

    if no block was provided



104
105
106
107
108
109
110
111
112
113
# File 'lib/weak/cache.rb', line 104

def fetch(key, skip_nil: false)
  raise ArgumentError, "must provide a block" unless block_given?

  @mutex.synchronize {
    @map.fetch(key) {
      value = yield(key)
      @map[key] = value unless skip_nil && value.nil?
    }
  }
end

#freezeself

Weak::Cache objects can't be frozen since this is not enforced by the underlying Map, resp. its ObjectSpace::WeakMap implementation. Thus, we try to signal this by not actually setting the frozen? flag and ignoring attempts to freeze us with just a warning.

Returns:

  • (self)


121
122
123
124
# File 'lib/weak/cache.rb', line 121

def freeze
  warn("Can't freeze #{self.class}")
  self
end

#inspectString

Returns a string containing a human-readable representation of the weak cache, e.g., "#<Weak::Cache {key1 => value1, key2 => value2, ...}>".

Returns:

  • (String)

    a string containing a human-readable representation of the weak cache, e.g., "#<Weak::Cache {key1 => value1, key2 => value2, ...}>"



129
130
131
# File 'lib/weak/cache.rb', line 129

def inspect
  @mutex.synchronize { "#<#{self.class} #{@map._inspect}>" }
end

#keysArray

Note:

In contrast to a Hash, Weak::Maps do not necessarily retain insertion order.

Returns an Array containing all keys of the map for which we have a valid value. Keys with garbage-collected values are excluded.

Returns:

  • (Array)

    an Array containing all keys of the map for which we have a valid value. Keys with garbage-collected values are excluded.

See Also:



134
135
136
# File 'lib/weak/cache.rb', line 134

def keys
  @mutex.synchronize { @map.keys }
end

#read(key) ⇒ Object Also known as: []

Note:

Map does not test member equality with == or eql?. Instead, it always checks strict object equality, so that, e.g., different String keys are not considered equal, even if they may contain the same content.

Returns the value associated with the given key, or nil if no value was found for the key.

Parameters:

  • key (Object)

    the key for the requested value

Returns:

  • (Object)

    the value associated with the given key, or nil if no value was found for the key



157
158
159
# File 'lib/weak/cache.rb', line 157

def read(key)
  @mutex.synchronize { @map[key] }
end

#sizeInteger Also known as: length

Returns the number of live key-value pairs in self.

Returns:

  • (Integer)

    the number of live key-value pairs in self



163
164
165
# File 'lib/weak/cache.rb', line 163

def size
  @mutex.synchronize { @map.size }
end

#to_h {|key, value| ... } ⇒ Hash

Returns a new Hash which considers object identity for keys which contains the key-value pairs in self.

Yields:

  • (key, value)

    When a block is given, returns a new Hash object whose content is based on the block; the block should return a 2-element Array object specifying the key-value pair to be included in the returned Hash.

Yield Parameters:

  • key (Object)

    the key of the current key-value pair

  • value (Object)

    the value of the current key-value pair

Returns:

  • (Hash)

    a new Hash which considers object identity for keys which contains the key-value pairs in self.



169
170
171
# File 'lib/weak/cache.rb', line 169

def to_h(&block)
  @mutex.synchronize { @map.to_h(&block) }
end

#write(key, value) ⇒ Object Also known as: []=

Note:

Map does not test member equality with == or eql?. Instead, it always checks strict object equality, so that, e.g., different String keys are not considered equal, even if they may contain the same content.

Associates the given value with the given key; returns value. If the given key exists, replaces its value with the given value.

Parameters:

  • key (Object)

    the key for the set key-value pair

  • value (Object)

    the value of the set key-value pair

Returns:

  • (Object)

    the given value



174
175
176
# File 'lib/weak/cache.rb', line 174

def write(key, value)
  @mutex.synchronize { @map[key] = value }
end