Make handles with reference counting for any resource.
- Zig 100%
| .forgejo/workflows | Fix CI | |
| example | Simplify Resource Handler Creation | |
| src | Remove Redundant Tag Name Compare | |
| .gitattributes | Initial Release | |
| .gitignore | Initial Release | |
| build.zig | Initial Release | |
| build.zig.zon | Remove Redundant Tag Name Compare | |
| LICENSE.md | Initial Release | |
| README.md | Remove Redundant Tag Name Compare | |
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
TextureLoadInfoof what information is passed for creating a new handle. - The resource stored by the handler is a
raylib.Texture, and loading it may case araylib.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 testto run the unit tests. - Run
zig buildto build all binaries. - Run
zig build run_exampleto 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.