Skip to content

Registry

Generated from engine/core/registry.h at 862e08b. The text under each declaration is the header's own comment, word for word. About the reference says how these pages are made.

Browse the core module

#include "engine/core/registry.h" · namespace labrador

How a resource is reached through the smart pointer that owns it. The primary template covers everything spelling it get() - unique_ptr, shared_ptr - and COM's ComPtr spells it Get(), so the D3D-facing code specialises this where COM is already in scope rather than dragging <wrl/client.h> in here.

static auto pointer(const Storage& storage);
class Registry

A store of named resources, and one lookup contract for every kind of resource: whichever way you ask, you get something live or a throw naming what was missing. It never returns nullptr and never inserts on a miss, so a misspelt name fails where it is written rather than null-dereferencing a frame later somewhere else.

There are two ways to ask, and the difference between them is the point:

resolve(name) -> Handle once, at load
get(handle) -> Resource* per frame - no string, no map, no compare

Per-frame code touches no string-keyed map (PHILOSOPHY T7, T8), so per-frame code never sees a name. get(name) remains for load-time callers that have one and want the resource immediately.

A name owns its slot for the registry's lifetime. Releasing a resource - what a device loss does to textures and fonts - empties the slot but keeps the mapping, so a handle resolved before the loss still names the right resource once the reload refills it. That is the whole reason a handle is a slot index and not a pointer: the pointer changes across a device restore and the slot does not.

The registry holds names, not meanings. What a name refers to is the caller's business - which is what lets a game keep its own resource types in one of these without the engine having to learn their vocabulary.

using handle = Handle<Resource>;
explicit Registry(const char* kind);

kind names the resource type in error messages: "Texture", "SpriteFont". It is stored, not copied, so it must outlive the registry - pass a literal.

void add(const std::string& name, Storage resource);

Fills the name's slot, claiming one if the name is new. Re-adding a name reuses its slot rather than appending, which is what keeps handles valid across a reload.

handle resolve(const std::string& name) const;

The load-time half. Throws std::out_of_range if nothing ever added the name: resolving a name no loader produced is a content bug, and this is the line that should report it.

Resolving is deliberately separate from reading, so a name can be turned into a handle once and the handle kept for the object's lifetime.

Resource* get(handle resource_handle) const;

The per-frame half: a bounds check and an indexed load. Never returns nullptr - an unresolved handle, or one whose slot has been released, throws instead.

Resource* get(const std::string& name) const;
bool contains(const std::string& name) const;

True only if the name is loaded now. A name whose slot has been released reads as absent, because a released resource is indistinguishable from a loaded one at every call site that only checks for presence.

void release_all();

Empties every slot and keeps every name, so handles survive the round trip through a device loss. Until the reload refills them, get() on any of these throws saying the resource was released - which is the honest answer and the one that names itself (T6).

Named in the public declarations above: Handle.

The files that include this header directly. A file can also reach it through another header.

Development documentation (unreleased). Built from Labrador 862e08b of 2026-10-08.