1
2
Fork
You've already forked ResourceHandles
0
Make handles with reference counting for any resource.
  • Zig 100%
Gota7 8c22743d9d
All checks were successful
test / Build Documentation (push) Successful in 20s
docs / Build & Deploy Documentation (push) Successful in 38s
test / Testing (push) Successful in 20s
test / Build Examples (push) Successful in 38s
Remove Redundant Tag Name Compare
2026年02月24日 20:44:18 -05:00
.forgejo/workflows Fix CI 2026年01月25日 15:51:07 -05:00
example Simplify Resource Handler Creation 2026年01月30日 20:03:03 -05:00
src Remove Redundant Tag Name Compare 2026年02月24日 20:44:18 -05:00
.gitattributes Initial Release 2026年01月25日 15:44:28 -05:00
.gitignore Initial Release 2026年01月25日 15:44:28 -05:00
build.zig Initial Release 2026年01月25日 15:44:28 -05:00
build.zig.zon Remove Redundant Tag Name Compare 2026年02月24日 20:44:18 -05:00
LICENSE.md Initial Release 2026年01月25日 15:44:28 -05:00
README.md Remove Redundant Tag Name Compare 2026年02月24日 20:44:18 -05:00

Resource Handles

Resource re-use with lazy loading and unloading for any resource.

Documentation

https://7games.codeberg.page/ResourceHandles/@docs

Features

  • Reference counting for any type of resource.
  • Only load resources when necessary, if the same resource load data is detected when creating a handle it will duplicate a handle and not re-load resources.
  • Only frees a resource when all handles to the resource are freed.
  • Handles are properly typed: for example, a "texture" resource handle can not be assigned to "model" resource handle.
  • Option to customize handle bitwidth as well as if handles are allowed to be reused.

Install

  • Run zig fetch --save=resource_handles git+https://codeberg.org/7Games/ResourceHandles#v2.0.1
  • Place in your build.zig:
my_module.addImport("resource_handles",b.dependency("resource_handles",.{.target=target,.optimize=optimize},).module("resource_handles"));

Getting Started

Let's say we wish to make a resource handler in raylib for caching textures. First, we will create the information we need to load a texture:

constTextureLoadInfo=struct{path:[:0]constu8,};

Next, we will create the loading and unloading functions for the texture:

fnloadRaylibTexture(resource_load_info:TextureLoadInfo,)raylib.RaylibError!raylib.Texture{returnraylib.loadTexture(resource_load_info.path);}fnunloadRaylibTexture(resource_load_info:TextureLoadInfo,resource:*raylib.Texture,)void{_=resource_load_info;raylib.unloadTexture(resource.*);}

After this, we are free to create the new resource handler:

constresource_handles=@import("resource_handles");constTextureResourceHandler=resource_handles.ResourceHandler(32,opaque{},.allow_reuse,loadRaylibTexture,unloadRaylibTexture,);

Some notes of the resource handler structure:

  • We are using TextureLoadInfo of what information is passed for creating a new handle.
  • The resource stored by the handler is a raylib.Texture, and loading it may case a raylib.RaylibError.
  • A handle for a texture will be 32-bits. Handles in this case may be repeated.
  • We must pass in an opaque {} such that if we to make a new resource handler, the type checker will catch accidental assignment of handles of different types.

Now, we are free to use the resource handler:

varresource_handler=TextureResourceHandler.init(allocator);deferresource_handler.deinit();// This will free all handles and resources.// How to get the type of handles used.constTextureHandle=TextureResourceHandler.Handle;// Load player 1 texture.constplayer1_texture:TextureHandle=tryresource_handler.createHandle(.{.path="res/img/player.png"});deferresource_handler.free(player1_texture)catch{};// May return an invalid handle error, but we don't care in this case.// Load the player 2 texture, since this uses the same load info it will just re-use the already loaded image.constplayer2_texture:TextureHandle=tryresource_handler.createHandle(.{.path="res/img/player.png"});deferresource_handler.free(player2_texture)catch{};// May return an invalid handle error, but we don't care in this case.// Player 3 texture can just duplicate the handle to the resource.// This creates a new handle/strong reference to the resource and increases the reference count and so is different from copying the handle from an assignment.constplayer3_texture:TextureHandle=tryresource_handler.dup(player1_texture);deferresource_handler.free(player3_texture)catch{};// May return an invalid handle error, but we don't care in this case.// Can get the texture, it will not be unloaded until all player handles are freed.// Using get for an invalid handle will throw an invalid handle error.// However, if handles are allowed to be reused you can not guarantee an invalid handle error if a new handle just so happens to align with an old one.raylib.drawTexture(tryresource_handler.get(player1_texture),player1_x,player1_y,.white);

Build Options

  • Run zig build test to run the unit tests.
  • Run zig build to build all binaries.
  • Run zig build run_example to run the example application. The example is most useful

Other Notes

  • The resource handler is not thread safe, you are responsible for proper locking mechanisms.
  • Duplicating a handle creates a new unique handle that must be freed in order for the resource to be free.
  • If handles are allowed to be reused you can not guarantee an invalid handle error is accurate if a new handle just so happens to align with an old one.