{"id":22071363,"url":"https://github.com/atilaneves/automem","last_synced_at":"2026-02-10T02:04:55.097Z","repository":{"id":18622079,"uuid":"84772786","full_name":"atilaneves/automem","owner":"atilaneves","description":"C++-style automatic memory management smart pointers for D","archived":false,"fork":false,"pushed_at":"2025-11-14T16:52:59.000Z","size":319,"stargazers_count":88,"open_issues_count":8,"forks_count":15,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-11-14T18:34:27.261Z","etag":null,"topics":["allocator","allocators","d","dlang","dlanguage","memory-management","nogc"],"latest_commit_sha":null,"homepage":null,"language":"D","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/atilaneves.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}},"created_at":"2017-03-13T01:51:21.000Z","updated_at":"2025-11-14T16:52:48.000Z","dependencies_parsed_at":"2024-01-18T16:25:46.137Z","dependency_job_id":"f176bb38-6e49-46f5-8b50-c69c463a33c9","html_url":"https://github.com/atilaneves/automem","commit_stats":null,"previous_names":[],"tags_count":40,"template":false,"template_full_name":null,"purl":"pkg:github/atilaneves/automem","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atilaneves%2Fautomem","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atilaneves%2Fautomem/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atilaneves%2Fautomem/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atilaneves%2Fautomem/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/atilaneves","download_url":"https://codeload.github.com/atilaneves/automem/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atilaneves%2Fautomem/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29288768,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-09T21:57:15.303Z","status":"online","status_checked_at":"2026-02-10T02:00:07.935Z","response_time":65,"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","allocators","d","dlang","dlanguage","memory-management","nogc"],"created_at":"2024-11-30T20:31:06.210Z","updated_at":"2026-02-10T02:04:55.082Z","avatar_url":"https://github.com/atilaneves.png","language":"D","funding_links":[],"categories":[],"sub_categories":[],"readme":"# automem - smart pointers for D\n\n[![Build Status](https://github.com/atilaneves/automem/workflows/CI/badge.svg)](https://github.com/atilaneves/automem/actions)\n[![Coverage](https://codecov.io/gh/atilaneves/automem/branch/master/graph/badge.svg)](https://codecov.io/gh/atilaneves/automem)\n[![Open on run.dlang.io](https://img.shields.io/badge/run.dlang.io-open-blue.svg)](https://run.dlang.io/is/P3yCpG)\n\n## C++-style automatic memory management smart pointers for D using `std.experimental.allocator`.\n\nUnlike the C++ variants, the smart pointers themselves allocate the memory for the objects they contain.\nThat ensures the right allocator is used to dispose of the memory as well.\n\nAllocators are template arguments instead of using `theAllocator` so\nthat these smart pointers can be used in `@nogc` code. However, they\nwill default to `typeof(theAllocator)` for simplicity. The examples\nabove will be explicit.\n\nAnother reason to have to pass in the type of allocator is to decide how it is to\nbe stored. Stateless allocators can be \"stored\" by value and imply zero-cost `Unique` pointers.\nSingleton allocators such as Mallocator (that have an `instance` attribute/member function)\ndon't need to be passed in to the constructor. This is detected at compile-time as an example\nof design by instrospection.\n\n`RefCounted` leverages D's type system by doing atomic reference counting *iff* the type of the contained\nobject is `shared`. Otherwise it's non-atomic.\n\nSample code:\n\n```d\n@safe unittest {\n\n    import std.algorithm: move;\n\n    static struct Point {\n        int x;\n        int y;\n    }\n\n    // set theAllocator as desired beforehand, e.g.\n    // theAllocator = allocatorObject(Mallocator.instance)\n\n    {\n        // must pass arguments to initialise the contained object\n        auto u1 = Unique!Point(2, 3);\n        assert(*u1 == Point(2, 3));\n        assert(u1.y == 3);\n\n        // auto u2 = u1; // won't compile, can only move\n        typeof(u1) u2 = () @trusted { return u1.move; }();\n        assert(cast(bool)u1 == false); // u1 is now empty\n    }\n    // memory freed for the Point structure created in the block\n\n    {\n        auto s1 = RefCounted!Point(4, 5);\n        assert(*s1 == Point(4, 5));\n        assert(s1.x == 4);\n        {\n            auto s2 = s1; // can be copied\n        } // ref count goes to 1 here\n\n    } // ref count goes to 0 here, memory released\n\n    {\n        import std.algorithm: map;\n        import std.range: iota;\n\n        // `vector` is also known as `array`\n        auto vec = vector(Point(1, 2), Point(3, 4), Point(5, 6));\n        assert(equal(vec.range, [Point(1, 2), Point(3, 4), Point(5, 6)]));\n\n        vec.length = 1;\n        assert(equal(vec.range, [Point(1, 2)]));\n\n        vec ~= Point(7, 8);\n        assert(equal(vec.range, [Point(1, 2), Point(7, 8)]));\n\n        vec ~= 2.iota.map!(i =\u003e Point(i + 10, i + 11));\n        assert(equal(vec.range, [Point(1, 2), Point(7, 8), Point(10, 11), Point(11, 12)]));\n    } // memory for the array released here\n}\n\n\n// @nogc test - must explicitly use the allocator for compile-time guarantees\n@system @nogc unittest {\n    import stdx.allocator.mallocator: Mallocator;\n\n    static struct Point {\n        int x;\n        int y;\n    }\n\n    {\n        // must pass arguments to initialise the contained object\n        auto u1 = Unique!(Point, Mallocator)(2, 3);\n        assert(*u1 == Point(2, 3));\n        assert(u1.y == 3);\n    }\n    // memory freed for the Point structure created in the block\n\n    // similarly for the other types\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fatilaneves%2Fautomem","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fatilaneves%2Fautomem","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fatilaneves%2Fautomem/lists"}