-
Notifications
You must be signed in to change notification settings - Fork 242
Expand file tree
/
Copy pathweak_key_map.rbs
More file actions
166 lines (160 loc) · 5.4 KB
/
weak_key_map.rbs
File metadata and controls
166 lines (160 loc) · 5.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
%a{annotate:rdoc:skip}
module ObjectSpace
# <!-- rdoc-file=weakmap.c -->
# An ObjectSpace::WeakKeyMap is a key-value map that holds weak references to
# its keys, so they can be garbage collected when there is no more references.
#
# Unlike ObjectSpace::WeakMap:
#
# * references to values are *strong*, so they aren't garbage collected while
# they are in the map;
# * keys are compared by value (using Object#eql?), not by identity;
# * only garbage-collectable objects can be used as keys.
#
# map = ObjectSpace::WeakKeyMap.new
# val = Time.new(2023, 12, 7)
# key = "name"
# map[key] = val
#
# # Value is fetched by equality: the instance of string "name" is
# # different here, but it is equal to the key
# map["name"] #=> 2023-12-07 00:00:00 +0200
#
# val = nil
# GC.start
# # There are no more references to `val`, yet the pair isn't
# # garbage-collected.
# map["name"] #=> 2023-12-07 00:00:00 +0200
#
# key = nil
# GC.start
# # There are no more references to `key`, key and value are
# # garbage-collected.
# map["name"] #=> nil
#
# (Note that GC.start is used here only for demonstrational purposes and might
# not always lead to demonstrated results.)
#
# The collection is especially useful for implementing caches of lightweight
# value objects, so that only one copy of each value representation would be
# stored in memory, but the copies that aren't used would be garbage-collected.
#
# CACHE = ObjectSpace::WeakKeyMap
#
# def make_value(**)
# val = ValueObject.new(**)
# if (existing = @cache.getkey(val))
# # if the object with this value exists, we return it
# existing
# else
# # otherwise, put it in the cache
# @cache[val] = true
# val
# end
# end
#
# This will result in `make_value` returning the same object for same set of
# attributes always, but the values that aren't needed anymore wouldn't be
# sitting in the cache forever.
#
class WeakKeyMap[K, V]
# <!--
# rdoc-file=weakmap.c
# - map[key] -> value
# -->
# Returns the value associated with the given `key` if found.
#
# If `key` is not found, returns `nil`.
#
def []: (K) -> V?
# <!--
# rdoc-file=weakmap.c
# - map[key] = value -> value
# -->
# Associates the given `value` with the given `key`
#
# The reference to `key` is weak, so when there is no other reference to `key`
# it may be garbage collected.
#
# If the given `key` exists, replaces its value with the given `value`; the
# ordering is not affected
#
def []=: (K, V?) -> V?
# <!--
# rdoc-file=weakmap.c
# - map.clear -> self
# -->
# Removes all map entries; returns `self`.
#
def clear: () -> self
# <!--
# rdoc-file=weakmap.c
# - map.delete(key) -> value or nil
# - map.delete(key) {|key| ... } -> object
# -->
# Deletes the entry for the given `key` and returns its associated value.
#
# If no block is given and `key` is found, deletes the entry and returns the
# associated value:
# m = ObjectSpace::WeakKeyMap.new
# key = "foo" # to hold reference to the key
# m[key] = 1
# m.delete("foo") # => 1
# m["foo"] # => nil
#
# If no block given and `key` is not found, returns `nil`.
#
# If a block is given and `key` is found, ignores the block, deletes the entry,
# and returns the associated value:
# m = ObjectSpace::WeakKeyMap.new
# key = "foo" # to hold reference to the key
# m[key] = 2
# m.delete("foo") { |key| raise 'Will never happen'} # => 2
#
# If a block is given and `key` is not found, yields the `key` to the block and
# returns the block's return value:
# m = ObjectSpace::WeakKeyMap.new
# m.delete("nosuch") { |key| "Key #{key} not found" } # => "Key nosuch not found"
#
def delete: (K) -> V?
| [T] (K) { (K) -> T } -> (V | T)
# <!--
# rdoc-file=weakmap.c
# - map.getkey(key) -> existing_key or nil
# -->
# Returns the existing equal key if it exists, otherwise returns `nil`.
#
# This might be useful for implementing caches, so that only one copy of some
# object would be used everywhere in the program:
#
# value = {amount: 1, currency: 'USD'}
#
# # Now if we put this object in a cache:
# cache = ObjectSpace::WeakKeyMap.new
# cache[value] = true
#
# # ...we can always extract from there and use the same object:
# copy = cache.getkey({amount: 1, currency: 'USD'})
# copy.object_id == value.object_id #=> true
#
def getkey: (untyped) -> K?
# <!--
# rdoc-file=weakmap.c
# - map.inspect -> new_string
# -->
# Returns a new String containing informations about the map:
#
# m = ObjectSpace::WeakKeyMap.new
# m[key] = value
# m.inspect # => "#<ObjectSpace::WeakKeyMap:0x00000001028dcba8 size=1>"
#
def inspect: () -> String
# <!--
# rdoc-file=weakmap.c
# - map.key?(key) -> true or false
# -->
# Returns `true` if `key` is a key in `self`, otherwise `false`.
#
def key?: (K) -> bool
end
end