Skip to content

← Memory, Copies and Slow Code step 15 of 38

Medium Primitives

Build a Registry That Does Not Keep Objects Alive

Build an InstanceRegistry that finds objects by a string key without keeping them alive. The starter stores ordinary references, so an object stays in the registry after every other part of the program has dropped it.

registry = InstanceRegistry()
db = Resource("db")
registry.register("db", db)
registry.get("db") is db  # True
del db
registry.get("db")        # None, the object was freed
len(registry)             # 0

What to write

  • register(key, obj) stores a weak reference to obj. Registering a key again replaces the old entry.
  • get(key) returns the object, or None if the key was never registered or its object has been freed.
  • len(registry) counts only the entries whose object is still alive.
  • If obj cannot be weakly referenced, register raises TypeError. Let that error reach the caller, and leave any earlier entry for that key as it was.

When you need the object, call its weak reference once, store the result in a local, and check the local. Your code must pass mypy --strict.

The registry may keep dead weak references inside, as long as get and len treat them as missing.

What the driver does

Keep Resource, SlottedResource and solve as they are. Resource is an ordinary class, so it supports weak references. SlottedResource is a dataclass with slots=True and no weakref_slot=True, so registering it raises TypeError.

solve(register, drop, probe_slotted) creates a Resource for each key in register and keeps the newest one for each key in a local dictionary. It checks that get returns those exact objects. Then it drops its references for the keys in drop and calls gc.collect(). A key that appears twice in drop, or was never registered, changes nothing more.

The report contains:

  • live: the sorted, distinct registered keys whose objects are still alive.
  • size: len(registry) at the end.
  • identity_ok: whether get returned the exact objects before the driver dropped any. It is True when register is empty.
  • slotted_error: "TypeError" if probe_slotted is true and registering a SlottedResource failed, otherwise "".

Going further

A registry that lives for the whole program should also delete dead entries, so that its dictionary of keys does not keep growing. A WeakValueDictionary does that for you.