Template Class ResourceReference

Class Documentation

template<ResourceConcept T>
class ResourceReference

Type-safe smart handle for asynchronously-loaded resources.

ResourceReference<T> is the primary interface for accessing resources loaded by the ResourceRegistry. It provides a handle-based API where references can exist before the resource finishes loading, enabling non-blocking async loading patterns.

Key Concepts:

Handle vs Resource: A ResourceReference is a handle to a resource, not the resource itself. The actual resource lives in the ResourceRegistry’s internal storage. Multiple references can point to the same resource, and references are cheap to copy.

Lazy State Synchronization: References cache their state (Unknown/Pending/Loaded/Error) and only query the registry when needed. Calling get_state() or is_valid() triggers a registry lookup if the cached state isn’t Loaded. This avoids redundant lookups and enables efficient state polling.

Reference Counting: The ReferenceManager tracks how many ResourceReferences point to each resource. This enables future features like automatic unloading when reference counts drop to zero. Copy/move operations automatically update the reference counts.

Thread Safety: State queries are thread-safe. The registry uses internal locking to ensure state transitions are atomic. However, the underlying resource (accessed via get()) must be used in accordance with its own thread-safety guarantees.

Distinction from Reference<T>:

  • Reference<T> = std::shared_ptr<T> - Generic ownership for any engine object

  • ResourceReference<T> = Smart handle for user assets with async loading semantics

Once a resource is loaded in the registry, it’s always valid. But a ResourceReference might point to a resource that’s still loading, failed, or doesn’t exist.

Usage Example (Async Loading):

// Request async load (returns immediately)
auto texture_ref = registry.load<TextureResource>(STRING_ID("textures/albedo.png"));

// First frame: resource is probably still loading
if (texture_ref.is_valid()) {
    // This branch won't execute yet
    auto& texture = texture_ref.get();
    renderer.bind_texture(texture);
} else {
    // Show loading placeholder
    renderer.bind_texture(default_texture);
}

// Later frames: resource finishes loading
if (texture_ref.is_valid()) {
    // Now this executes - texture is ready
    auto& texture = texture_ref.get();
    renderer.bind_texture(texture);
}

Usage Example (Synchronous Loading):

// Block until loaded (for critical startup resources)
auto mesh_ref = registry.immediate_load<MeshResource>(STRING_ID("models/character.gltf"));
// mesh_ref.is_valid() is guaranteed true here (or Error if load failed)

Usage Example (Error Handling):

auto shader_ref = registry.load<ShaderResource>(STRING_ID("shaders/pbr.slang"));

switch (shader_ref.get_state()) {
    case ResourceState::Loaded:
        // Ready to use
        break;
    case ResourceState::Pending:
        // Still loading, try again next frame
        break;
    case ResourceState::Error:
        // Load failed, use fallback
        LOG_ERROR("Failed to load shader");
        shader_ref = registry.get<ShaderResource>(STRING_ID("shaders/fallback.slang"));
        break;
    case ResourceState::Missing:
        // File doesn't exist
        LOG_ERROR("Shader file not found");
        break;
}

See also

ResourceRegistry::load() for async loading

See also

ResourceRegistry::immediate_load() for blocking loading

See also

ResourceRegistry::get() for retrieving already-loaded resources

See also

ResourceState for all possible states

See also

ReferenceManager for reference counting details

Note

Default-constructed references are in Null state and is_valid() returns false

Note

Moved-from references become Null

Note

operator-> and operator* dont check if the resource isn’t loaded - use is_valid() first

Template Parameters:

T – The resource type (must satisfy ResourceConcept)

Public Functions

ResourceReference() = default

Default constructor - creates a Null reference.

inline explicit ResourceReference(std::nullptr_t)

Nullptr constructor - creates a Null reference.

inline ~ResourceReference()
inline ResourceReference(const ResourceReference &other)
inline ResourceReference(ResourceReference &&other) noexcept
inline ResourceReference &operator=(const ResourceReference &other)
inline ResourceReference &operator=(ResourceReference &&other) noexcept
inline ResourceState get_state() const

Returns the current state of the resource in the registry,

Note

in all other states than ResourceState::Loaded the underlying resource pointer will be null.

Returns:

The state of the resource in the registry

inline bool is_valid() const

Checks if the resource in valid in the registry (loaded)

Note

this function will lazily load the resource into the reference if the resource was unloaded before and now is loaded

Returns:

True if the resource is loaded, false otherwise

inline T *get() const

Returns the underlying pointer to the resource, with nullptr otherwise.

Note

Please use after validation the state of the reference using is_valid or get_state

Returns:

A pointer to the underlying resource, nullptr otherwise

inline T *operator->()
inline T &operator*()
inline const T *operator->() const
inline const T &operator*() const
inline Reference<T> underlying()
Returns:

The underlying Reference class to the resource

inline Reference<T> underlying() const
inline bool operator==(const ResourceReference &other) const
template<ResourceConcept U>
inline ResourceReference<U> cast() const