{"id":28068600,"url":"https://github.com/nahratzah/cycle_ptr","last_synced_at":"2025-05-12T17:35:02.959Z","repository":{"id":48744727,"uuid":"135625776","full_name":"nahratzah/cycle_ptr","owner":"nahratzah","description":"Smart pointers that do the right thing with cycles.","archived":false,"fork":false,"pushed_at":"2023-02-10T21:05:45.000Z","size":192,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2023-03-29T13:41:25.526Z","etag":null,"topics":["cpp17","garbage-collection","smart-pointer"],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nahratzah.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}},"created_at":"2018-05-31T19:18:38.000Z","updated_at":"2022-12-29T19:00:11.000Z","dependencies_parsed_at":"2023-02-08T07:15:14.360Z","dependency_job_id":null,"html_url":"https://github.com/nahratzah/cycle_ptr","commit_stats":null,"previous_names":[],"tags_count":null,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nahratzah%2Fcycle_ptr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nahratzah%2Fcycle_ptr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nahratzah%2Fcycle_ptr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nahratzah%2Fcycle_ptr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nahratzah","download_url":"https://codeload.github.com/nahratzah/cycle_ptr/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253788502,"owners_count":21964535,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["cpp17","garbage-collection","smart-pointer"],"created_at":"2025-05-12T17:34:52.312Z","updated_at":"2025-05-12T17:35:02.943Z","avatar_url":"https://github.com/nahratzah.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build Status](https://travis-ci.org/nahratzah/cycle_ptr.svg?branch=master)](https://travis-ci.org/nahratzah/cycle_ptr)\n\n# Cycle Pointer library\n\nThis library is a smart pointer library, that allows for cycles in\ndatastructures.\n\nBasically, if you have a case where:\n\n    class A;\n    class B;\n\n    class A {\n    public:\n      std::shared_ptr\u003cB\u003e b;\n    };\n\n    class B {\n    public:\n      std::shared_ptr\u003cA\u003e a;\n    };\n\n    int main() {\n      std::shared_ptr\u003cA\u003e a_ptr = std::make_shared\u003cA\u003e();\n      std::shared_ptr\u003cB\u003e b_ptr = std::make_shared\u003cB\u003e();\n\n      a_ptr-\u003eb = b_ptr;\n      b_ptr-\u003ea = a_ptr;\n\n      a_ptr.reset();\n      b_ptr.reset();\n      // We now leaked A and B!\n    }\n\nis what you need, but you want to avoid the resulting memory leak, this library\nmay offer a solution.\n\nThe equivalent code in this library would be:\n\n    class A;\n    class B;\n\n    class A {\n    public:\n      cycle_ptr::cycle_member_ptr\u003cB\u003e b;\n    };\n\n    class B {\n    public:\n      cycle_ptr::cycle_member_ptr\u003cA\u003e a;\n    };\n\n    int main() {\n      cycle_ptr::cycle_gptr\u003cA\u003e a_ptr = cycle_ptr::make_cycle\u003cA\u003e();\n      cycle_ptr::cycle_gptr\u003cB\u003e b_ptr = cycle_ptr::make_cycle\u003cB\u003e();\n\n      a_ptr-\u003eb = b_ptr;\n      b_ptr-\u003ea = a_ptr;\n\n      a_ptr.reset();\n      b_ptr.reset();\n      // A and B are now unreachable, so cycle_ptr cleans them up properly.\n    }\n\n## Reference\n\nDoxygen output is [viewable online](https://www.stack.nl/~ariane/cycle_ptr/).\n\n## Overview\n\nThis library contains three pointers, which form the core of its interface.\n\n1. ``cycle_ptr::cycle_member_ptr`` represents a relationship between two\n   objects.\n2. ``cycle_ptr::cycle_gptr`` represents a global pointer\n   (that's what the ``g`` stands for... I should not be allowed to come up\n   with names).\n   This pointer is also used for function arguments and variables at function\n   scope.\n3. ``cycle_ptr::cycle_weak_ptr`` represents a weak pointer to an object.\n\n``cycle_ptr::cycle_member_ptr`` and ``cycle_ptr::cycle_gptr`` operate similar\nto ``std::shared_ptr``.\n``cycle_ptr::cycle_weak_ptr`` is the equivalent of ``std::weak_ptr``.\n\n## Dealing With Collections\n\nConsider a collection: ``std::vector\u003ccycle_ptr::cycle_gptr\u003cMyClass\u003e\u003e``.\n\nThis collection is not suitable for use inside an object that participates\nin the cycle\\_ptr graph, as the link would not be modeled.\n\nThe alternative is to use ``std::vector\u003ccycle_ptr::cycle_member_ptr\u003cMyClass\u003e\u003e``,\nbut this would not be usable outside of an object participating in the graph.\n\nThe solution to this, is to use ``cycle_ptr::cycle_allocator\u003cAlloc\u003e``.\nThis allocator adapts an allocator ``Alloc``, by allowing cycle\\_member\\_ptr\nto deduce its owner at construction.\n\n    class MyClass;\n\n    using MyClassVector = std::vector\u003c\n        cycle_ptr::cycle_gptr\u003cMyClass\u003e,\n        cycle_ptr::cycle_allocator\u003cstd::allocator\u003ccycle_ptr::cycle_gptr\u003cMyClass\u003e\u003e\u003e\u003e;\n\n    class MyClass\n    : public cycle_ptr::cycle_base // Used as argument to allocator.\n    {\n      // Vector instantiated with allocator that enforces ownership from *this.\n      MyClassVector data = MyClassVector(MyClassVector::allocator_type(*this));\n    };\n\n    // Create a MyClassVector that does not have an owner object.\n    MyClassVector notAMember = MyClassVector(MyClassVector::allocator_type(cycle_ptr::unowned_cycle));\n\n    void example(cycle_ptr::cycle_gptr\u003cMyClass\u003e ptr) {\n      MyClass.data = notAMember; // Using copy assignment from std::vector.\n    }\n\nWith this allocator, copy construction should *always* supply an allocator\nsuch that ownership is explicitly stated.\nWhile move constructor silently succeeds, care should be taken not to break\nownership rules.\n\nThe vector in this example uses pointers to demonstrate usage, but it works\nequally well with structs or classes containing member pointers.\n\n## Configuring\n\nThe library allows for limited control of the GC operations, using\n``cycle_ptr::gc_operation`` and related functions.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnahratzah%2Fcycle_ptr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnahratzah%2Fcycle_ptr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnahratzah%2Fcycle_ptr/lists"}