{"id":51290031,"url":"https://github.com/jokruger/refpool","last_synced_at":"2026-06-30T09:30:27.887Z","repository":{"id":360672450,"uuid":"1251188581","full_name":"jokruger/refpool","owner":"jokruger","description":"Reference-counted value pool for Go with compact integer handles, segmented storage, freelist reuse, and arena-style reset.","archived":false,"fork":false,"pushed_at":"2026-06-18T12:06:53.000Z","size":100,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-18T14:08:16.151Z","etag":null,"topics":["allocator","arena","go","golang","memory-management","pool"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jokruger.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-27T10:28:51.000Z","updated_at":"2026-06-18T12:06:01.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/jokruger/refpool","commit_stats":null,"previous_names":["jokruger/refpool"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/jokruger/refpool","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jokruger%2Frefpool","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jokruger%2Frefpool/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jokruger%2Frefpool/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jokruger%2Frefpool/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jokruger","download_url":"https://codeload.github.com/jokruger/refpool/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jokruger%2Frefpool/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34961541,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-30T02:00:05.919Z","response_time":92,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["allocator","arena","go","golang","memory-management","pool"],"created_at":"2026-06-30T09:30:25.858Z","updated_at":"2026-06-30T09:30:27.876Z","avatar_url":"https://github.com/jokruger.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# refpool\n\nrefpool is a Go package for allocating, retaining, releasing, and reusing values\nthrough compact integer handles.\n\nIt is designed for systems that need stable resource identifiers without\nexposing raw pointers, such as virtual machines, interpreters, scripting\nruntimes, entity stores, and tagged/boxed value representations. Values are\nstored internally in segmented arrays, allowing handles to be resolved to\npointers in constant time while avoiding large contiguous allocations.\n\nUnlike `sync.Pool`, refpool gives each allocated value an integer handle that\ncan be stored, copied, tagged, or embedded inside a VM value. Unlike a simple\narena, values can be individually released through reference counting and later\nreused through a free-list. A global reset operation is also provided for\narena-style lifetime management when all values can be discarded together.\n\nThe package is intended to reduce GC pressure, minimize heap allocations, and\nmake resource ownership explicit in performance-sensitive Go programs.\n\n## Concurrency\n\n`Pool` and `Arena` are intentionally not concurrency-safe. They do not use atomics or locks\naround allocation, reference counting, free-list updates, or resets.\n\nThis keeps the hot path small for single-threaded runtimes, arena-like phases,\nand systems that already have ownership or scheduling guarantees. If a pool is\nshared across goroutines, the caller must provide external synchronization.\n\n## Pool\n\n`Pool[T]` is a single-type, typed generic pool. Create one with `NewPool[T]` and interact\nwith it through methods on the returned pointer.\n\n## Arena\n\n`Arena` is a multi-type pool that hosts up to 256 independent typed sub-pools, each\nidentified by a `Type` (a `uint8`). This lets a single arena manage all resource\ntypes for a subsystem — such as a virtual machine or compiler pass — and reset them\nall in bulk.\n\n### Creating an Arena\n\n```go\narena := refpool.NewArena(\n    refpool.With[MyStruct](myType, 1024),   // pre-allocate 1024 slots of type MyStruct\n    refpool.With[string](strType, 512),     // pre-allocate 512 string slots\n    refpool.WithZeroOnRelease(false),       // optional: skip zeroing on Release\n)\n```\n\nEach `With[T](pool, preAlloc)` option registers a pool for the given `Type` identifier and\npre-allocates at least `preAlloc` slots. `WithZeroOnRelease` applies to all sub-pools.\n\n### Arena Usage Rules\n\n`Reference(0)` is reserved as the invalid/nil reference. The same rules that apply to\n`Pool` apply to each sub-pool within an `Arena`:\n\n- Call `Retain` whenever a logical copy of a reference is created.\n- Each `Retain` must be matched by a `Release`, unless the slot is pinned.\n- `Pin` marks a slot as arena-owned; `Retain`/`Release` have no effect on pinned slots.\n- `Resolve` returns a temporary pointer — do not store it.\n- After `Reset`, old references must not be used until their slots are re-allocated.\n\n### Arena API\n\n| Function / Method | Description |\n|---|---|\n| `NewArena(opts...)` | Creates a new Arena with the given options. |\n| `With[T](pool, preAlloc)` | Registers type `T` for `pool` and pre-allocates slots. |\n| `WithZeroOnRelease(flag)` | Controls whether `Release` zeroes the value (default `true`). |\n| `arena.New(pool)` | Allocates (or reuses) a slot; returns `(Reference, any, bool)`. |\n| `arena.Resolve(pool, r)` | Returns `any` pointer for the reference. |\n| `Resolve[T](arena, pool, r)` | Generic helper; returns a typed `*T`. |\n| `arena.Retain(pool, r)` | Increments reference count. |\n| `arena.Release(pool, r)` | Decrements reference count; frees slot at zero. |\n| `arena.Pin(pool, r)` | Pins a slot; bypasses reference counting. |\n| `arena.Reset(pool)` | Drops extra chunks and resets the free-list for `pool`. |\n| `arena.Stats(pool)` | Returns `(allocated, free int)` for `pool`. |\n\n### Arena Example\n\n```go\npackage main\n\nimport (\n  \"fmt\"\n\n  \"github.com/jokruger/refpool\"\n)\n\nconst (\n  TypeNode refpool.Type = 0\n  TypeEdge refpool.Type = 1\n)\n\ntype Node struct{ Label string }\ntype Edge struct{ From, To refpool.Reference }\n\nfunc main() {\n  arena := refpool.NewArena(\n    refpool.With[Node](TypeNode, 1024),\n    refpool.With[Edge](TypeEdge, 2048),\n  )\n\n  nRef, nAny, ok := arena.New(TypeNode)\n  if !ok {\n    panic(\"arena overflow\")\n  }\n  nAny.(*Node).Label = \"root\"\n\n  eRef, eAny, ok := arena.New(TypeEdge)\n  if !ok {\n    panic(\"arena overflow\")\n  }\n  eAny.(*Edge).From = nRef\n\n  fmt.Println(refpool.Resolve[Node](arena, TypeNode, nRef).Label) // root\n  fmt.Println(refpool.Resolve[Edge](arena, TypeEdge, eRef).From == nRef) // true\n\n  arena.Retain(TypeNode, nRef)\n  arena.Release(TypeNode, nRef)\n  arena.Release(TypeNode, nRef) // final release — slot returned to free-list\n\n  // Bulk reset for next cycle.\n  arena.Reset(TypeNode)\n  arena.Reset(TypeEdge)\n}\n```\n\n\n\n## Pool Usage Rules\n\n`Reference(0)` is reserved as an invalid / nil reference. References returned by\n`NewPool` are compact integer handles and may be stored or copied, but the pointer\nreturned by `Resolve` is temporary and must not be retained.\n\nUse `Retain` whenever a logical copy of a reference is created and may outlive\nthe original owner. Each retained reference must eventually be matched by a\n`Release`, unless the value is pinned.\n\n`Release` decrements the reference count. When the count reaches zero, the value\nis reset to the zero value of `T` and the slot is added to the free-list for\nreuse. This zeroing is enabled by default and can be disabled per pool with\n`SetZeroOnRelease(false)` for throughput-focused workloads.\n\n`Pin` marks a value as pool-owned until the next reset. Pinned values are not\nreference-counted, so `Retain` and `Release` have no effect on them. Values are\nalso pinned automatically if the reference count reaches `math.MaxUint32`.\n\n`Reset` clears all currently allocated values and keeps all chunks for reuse.\nReset zeroing is enabled by default and can be disabled per pool with\n`SetZeroOnReset(false)` for throughput-focused workloads that can tolerate value\nretention between reset cycles.\n`ResetFull` also drops chunks allocated after pool creation. After either reset,\nold references must not be used until their slots are allocated again by `NewPool`.\n\n## Example\n\n```go\npackage main\n\nimport (\n  \"fmt\"\n\n  \"github.com/jokruger/refpool\"\n)\n\ntype Object struct {\n  Name string\n}\n\nfunc main() {\n  pool := refpool.NewPool[Object](1024)\n\n  ref, obj, ok := pool.New()\n  if !ok {\n    panic(\"refpool overflow\")\n  }\n  obj.Name = \"alpha\"\n\n  // Logical copy: retain once per extra owner.\n  pool.Retain(ref)\n\n  // Resolve by handle when needed.\n  fmt.Println(pool.Resolve(ref).Name) // alpha\n\n  // Release all owners.\n  pool.Release(ref)\n  pool.Release(ref)\n\n  // Slot can now be reused.\n  reusedRef, reusedObj, ok := pool.New()\n  if !ok {\n    panic(\"refpool overflow\")\n  }\n  reusedObj.Name = \"beta\"\n  fmt.Println(reusedRef == ref) // often true (free-list reuse)\n}\n```\n\n## Install\n\nRun `go get github.com/jokruger/refpool`\n\n## License\n\nThis project is licensed under the MIT License. See the `LICENSE` file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjokruger%2Frefpool","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjokruger%2Frefpool","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjokruger%2Frefpool/lists"}