Update object_cache.py
clean code
This commit is contained in:
parent
47bc91ff20
commit
353cf22dfb
@ -1,4 +1,6 @@
|
|||||||
from typing import Dict, List
|
from collections import defaultdict
|
||||||
|
from typing import Dict, List, Optional
|
||||||
|
import weakref
|
||||||
|
|
||||||
from .objects import MusicObject
|
from .objects import MusicObject
|
||||||
|
|
||||||
@ -9,52 +11,96 @@ This is necessary, to not have duplicate objects with the same id.
|
|||||||
Using a cache that maps the ojects to their id has multiple benefits:
|
Using a cache that maps the ojects to their id has multiple benefits:
|
||||||
- if you modify the object at any point, all objects with the same id get modified *(copy by reference)*
|
- if you modify the object at any point, all objects with the same id get modified *(copy by reference)*
|
||||||
- less ram usage
|
- less ram usage
|
||||||
|
- to further decrease ram usage I only store weak refs and not a strong reference, for the gc to still work
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
class ObjectCache:
|
class ObjectCache:
|
||||||
"""
|
"""
|
||||||
:attr object_to_id: maps any object from the Database like Song or Artist to its id.
|
ObjectCache is a cache for the objects retrieved from a database.
|
||||||
"""
|
It maps each object to its id and uses weak references to manage its memory usage.
|
||||||
|
Using a cache for these objects provides several benefits:
|
||||||
|
|
||||||
|
- Modifying an object updates all objects with the same id (due to copy by reference)
|
||||||
|
- Reduced memory usage
|
||||||
|
|
||||||
|
:attr object_to_id: Dictionary that maps MusicObjects to their id.
|
||||||
|
:attr weakref_map: Dictionary that uses weak references to MusicObjects as keys and their id as values.
|
||||||
|
|
||||||
|
:method exists: Check if a MusicObject already exists in the cache.
|
||||||
|
:method append: Add a MusicObject to the cache if it does not already exist.
|
||||||
|
:method extent: Add a list of MusicObjects to the cache.
|
||||||
|
:method remove: Remove a MusicObject from the cache by its id.
|
||||||
|
:method get: Retrieve a MusicObject from the cache by its id. """
|
||||||
object_to_id: Dict[str, MusicObject]
|
object_to_id: Dict[str, MusicObject]
|
||||||
|
weakref_map: Dict[weakref.ref, str]
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.object_to_id = dict()
|
self.object_to_id = dict()
|
||||||
|
self.weakref_map = defaultdict()
|
||||||
|
|
||||||
def clear(self) -> None:
|
|
||||||
"""
|
|
||||||
deletes all references and lets the gc clean up the rest
|
|
||||||
this should free up memorie.
|
|
||||||
|
|
||||||
If not, check if you have any references to an object in you're code.
|
|
||||||
It is likely that this object crossreferences to many objects
|
|
||||||
"""
|
|
||||||
self.object_to_id = dict()
|
|
||||||
|
|
||||||
def exists(self, music_object: MusicObject) -> bool:
|
def exists(self, music_object: MusicObject) -> bool:
|
||||||
"""
|
"""
|
||||||
:returns exist: if an element with the same id exists it returns true, else false
|
Check if a MusicObject with the same id already exists in the cache.
|
||||||
|
|
||||||
|
:param music_object: The MusicObject to check for.
|
||||||
|
:return: True if the MusicObject exists, False otherwise.
|
||||||
"""
|
"""
|
||||||
if music_object.dynamic:
|
if music_object.dynamic:
|
||||||
return True
|
return True
|
||||||
if music_object.id in self.object_to_id:
|
return music_object.id in self.object_to_id
|
||||||
return True
|
|
||||||
return False
|
def on_death(self, weakref_: weakref.ref) -> None:
|
||||||
|
"""
|
||||||
|
Callback function that gets triggered when the reference count of a MusicObject drops to 0.
|
||||||
|
This function removes the MusicObject from the cache.
|
||||||
|
|
||||||
|
:param weakref_: The weak reference of the MusicObject that has been garbage collected.
|
||||||
|
"""
|
||||||
|
data_id = self.weakref_map.pop(weakref_)
|
||||||
|
self.object_to_id.pop(data_id)
|
||||||
|
|
||||||
def append(self, music_object: MusicObject) -> bool:
|
def append(self, music_object: MusicObject) -> bool:
|
||||||
"""
|
"""
|
||||||
:returns exist: if an element with the same id exists it returns true, else false
|
Add a MusicObject to the cache.
|
||||||
|
|
||||||
|
:param music_object: The MusicObject to add to the cache.
|
||||||
|
:return: True if the MusicObject already exists in the cache, False otherwise.
|
||||||
"""
|
"""
|
||||||
if self.exists(music_object):
|
if self.exists(music_object):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
self.weakref_map[weakref.ref(music_object, self.on_death)] = music_object.id
|
||||||
self.object_to_id[music_object.id] = music_object
|
self.object_to_id[music_object.id] = music_object
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def extent(self, music_object_list: List[MusicObject]):
|
def extent(self, music_object_list: List[MusicObject]):
|
||||||
"""
|
"""
|
||||||
adjacent to the extend method of list, this appends n Object
|
adjacent to the extent method of list, this appends n Object
|
||||||
"""
|
"""
|
||||||
for music_object in music_object_list:
|
for music_object in music_object_list:
|
||||||
self.append(music_object)
|
self.append(music_object)
|
||||||
|
|
||||||
|
def remove(self, _id: str):
|
||||||
|
"""
|
||||||
|
Remove a MusicObject from the cache.
|
||||||
|
|
||||||
|
:param _id: The id of the MusicObject to remove from the cache.
|
||||||
|
"""
|
||||||
|
data = self.object_to_id.get(_id)
|
||||||
|
if data:
|
||||||
|
self.weakref_map.pop(weakref.ref(data))
|
||||||
|
self.object_to_id.pop(_id)
|
||||||
|
|
||||||
|
def __getitem__(self, item) -> Optional[MusicObject]:
|
||||||
|
"""
|
||||||
|
this returns the data obj
|
||||||
|
:param item: the id of the music object
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self.object_to_id.get(item)
|
||||||
|
|
||||||
|
def get(self, _id: str) -> Optional[MusicObject]:
|
||||||
|
return self.__getitem__(_id)
|
||||||
|
Loading…
Reference in New Issue
Block a user