TestGame/addons/reactivex/internal/weakkeydictionary.gd

125 lines
3.2 KiB
GDScript3
Raw Normal View History

2024-12-27 21:00:07 +01:00
class_name WeakKeyDictionary
## A dictionary with weak references to keys
##
## Pairs with non-referenced keys are automatically removed when deleted.
## Each [b]n[/b] insertions, a garbage collection step is performed.
var _data : Dictionary
var _lock : ReadWriteLock
var n : int
var _count : int
func _init(from : Dictionary = {}, n_insertions : int = 100):
self._data = {}
self._lock = ReadWriteLock.new()
for key in from.keys():
set_pair(key, from[key])
self.n = n_insertions
self._count = 0
func _hash_key(key) -> int:
return hash(key)
func _collect_garbage():
var dead_keys : Array = []
for hkey in self._data.keys():
if self._data[hkey].at(0).get_ref() == null:
dead_keys.push_back(hkey)
for hkey in dead_keys:
self._data.erase(hkey)
func set_pair(key, value):
if GDRx.assert_(key != null, "Key is NULL!"):
return
if GDRx.assert_(key is Object, "Key needs to be of type 'Object'"):
return
var hkey = self._hash_key(key)
var __ = ReadWriteLockGuard.new(self._lock, false)
self._data[hkey] = Tuple.new([weakref(key), value])
self._count += 1
if self._count >= n:
self._count = 0
self._collect_garbage()
func get_value(key, default = null) -> Variant:
if GDRx.assert_(key != null, "Key is NULL!"):
return
if GDRx.assert_(key is Object, "Key needs to be of type 'Object'"):
return
var hkey = self._hash_key(key)
var __ = ReadWriteLockGuard.new(self._lock, true)
if self._data.has(hkey):
return self._data[hkey].at(1)
return default
func find_key(value) -> Variant:
var __ = ReadWriteLockGuard.new(self._lock, true)
for tup in self._data.values():
if GDRx.eq(tup.at(1), value):
return tup.at(0).get_ref()
return null
func to_hash() -> int:
var __ = ReadWriteLockGuard.new(self._lock, true)
return self._data.hash()
func is_empty() -> bool:
var __ = ReadWriteLockGuard.new(self._lock, true)
return self._data.is_empty()
func clear():
var __ = ReadWriteLockGuard.new(self._lock, false)
self._data.clear()
self._count = 0
func erase(key) -> bool:
if GDRx.assert_(key != null, "Key is NULL!"):
return false
if GDRx.assert_(key is Object, "Key needs to be of type 'Object'"):
return false
var hkey = self._hash_key(key)
var __ = ReadWriteLockGuard.new(self._lock, false)
return self._data.erase(hkey)
func values() -> Array:
var res : Array = []
var __ = ReadWriteLockGuard.new(self._lock, true)
for tup in self._data.values():
res.push_back(tup.at(1))
return res
func size() -> int:
var __ = ReadWriteLockGuard.new(self._lock, true)
return self._data.size()
func keys() -> Array:
var res : Array = []
var __ = ReadWriteLockGuard.new(self._lock, true)
for tup in self._data.values():
var key = tup.at(0).get_ref()
if key:
res.push_back(key)
return res
func has_key(key) -> bool:
if GDRx.assert_(key != null, "Key is NULL!"):
return false
if GDRx.assert_(key is Object, "Key needs to be of type 'Object'"):
return false
var hkey = self._hash_key(key)
var __ = ReadWriteLockGuard.new(self._lock, true)
return self._data.has(hkey)
func has_all(keys_ : Array) -> bool:
var _keys = keys_.duplicate()
_keys.all(func(elem): return self._hash_key(elem))
var __ = ReadWriteLockGuard.new(self._lock, true)
return self._data.has_all(_keys)