{"id":19620954,"url":"https://github.com/secti6n/gc","last_synced_at":"2026-05-13T01:05:28.857Z","repository":{"id":82302297,"uuid":"141002748","full_name":"secti6n/gc","owner":"secti6n","description":null,"archived":false,"fork":false,"pushed_at":"2018-03-18T06:36:26.000Z","size":5,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-02-26T18:53:26.895Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"bhuztez/gc","license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/secti6n.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":null,"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}},"created_at":"2018-07-15T06:05:48.000Z","updated_at":"2018-07-15T06:05:50.000Z","dependencies_parsed_at":null,"dependency_job_id":"db9bfdfe-e5a3-40c4-9f8b-5ac321a14624","html_url":"https://github.com/secti6n/gc","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/secti6n/gc","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/secti6n%2Fgc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/secti6n%2Fgc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/secti6n%2Fgc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/secti6n%2Fgc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/secti6n","download_url":"https://codeload.github.com/secti6n/gc/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/secti6n%2Fgc/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32963180,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-12T23:30:32.555Z","status":"ssl_error","status_checked_at":"2026-05-12T23:30:18.191Z","response_time":102,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":[],"created_at":"2024-11-11T11:20:43.612Z","updated_at":"2026-05-13T01:05:28.828Z","avatar_url":"https://github.com/secti6n.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"==\ngc\n==\n\n.. image:: https://travis-ci.org/bhuztez/gc.svg?branch=master\n    :target: https://travis-ci.org/bhuztez/gc\n\nprecise garbage collection for C++\n\nTo deal with circular references, a garbage collector has to keep track of all\nreferences between garbage collected objects. Typically, for statically typed\nlanguage, a list of offsets to all references to other garbage collected objects\nis generated at compile time for each type. This is also possible in C++ to some\nextent.\n\nDespite C++ puts a strong emphasis on compile-time programming, C++ experts\nprefer to do this at runtime. For example, last year, Herb Sutter `talked about\nhis gcpp`__ . It plays the same trick as `Smieciuch Garbage Collector`__, which\nhas been around for over a decade. They have to check if a pointer is located in\nGC heap or not when constructor is called and record the address of the\npointer. This will make a moving garbage collector sick.\n\n.. code:: c++\n\n    struct gcptr {\n       gcptr(...) {\n         if (located_in_gc_heap(this)) {\n           // this is a pointer from non-root\n         } else {\n           // this is a pointer from root\n         }\n       }\n     }\n\n.. __: https://herbsutter.com/2016/09/22/my-talk-tomorrow-and-a-little-experimental-library/\n.. __: http://smieciuch.sourceforge.net/\n\n\nSince pointer to member can be used as a template argument, and with stateful\nmetaprograming, especially `friend injection techique discovered by Filip\nRoséen`__ , they can be stored in a compile-time list. Then we initialize the\nstatic variable used by the garbage collector, by a call to a constexpr\nfunction, which returns an array of offsets and its size.\n\n.. __: http://b.atch.se/posts/non-constant-constant-expressions/\n\nHere is a simple example. :code:`gc.hpp` implements the same algorithm as\ndescribed in `Garbage Collection for Python`__ . As you can see, two Cycle\nobjects which references to each other, are destructed, after\n:code:`::gc::collect()`.\n\n.. __: http://arctrix.com/nas/python/gc/\n\n.. code:: c++\n\n    // example.cpp\n    #include \u003ccassert\u003e\n    #include \u003calgorithm\u003e\n    #include \"gc.hpp\"\n\n\n    struct Counter {\n      static ::std::size_t count;\n      bool valid;\n\n      Counter()\n        : valid(true) {\n      }\n\n      Counter(Counter \u0026\u0026o) noexcept : valid(false) {\n        ::std::swap(valid, o.valid);\n      }\n\n      Counter \u0026\n      operator=(Counter \u0026\u0026) = delete;\n\n      Counter(Counter const \u0026) = delete;\n      Counter \u0026\n      operator=(const Counter \u0026) = delete;\n\n      ~Counter() {\n        if (valid)\n          count++;\n      }\n    };\n\n    ::std::size_t Counter::count = 0;\n\n\n    struct Cycle {\n      GC_OBJECT(Cycle);\n      Counter c;\n      ::gc::Ptr\u003cCycle\u003e GC_MEMBER(peer);\n    };\n\n\n    int\n    main() {\n      {\n        Counter::count = 0;\n        {\n          auto p = ::gc::make\u003cCounter\u003e({});\n        }\n        assert(Counter::count == 1);\n      }\n\n      {\n        Counter::count = 0;\n        {\n          ::gc::Ptr\u003cCounter\u003e p1;\n          {\n            auto p2 = ::gc::make\u003cCounter\u003e({});\n            p1 = p2;\n          }\n          assert(Counter::count == 0);\n          ::gc::collect();\n          assert(Counter::count == 0);\n        }\n\n        assert(Counter::count == 1);\n      }\n\n      {\n        Counter::count = 0;\n        {\n          auto p1 = ::gc::make\u003cCycle\u003e({});\n          auto p2 = ::gc::make\u003cCycle\u003e({});\n          p1-\u003epeer = p2;\n          p2-\u003epeer = p1;\n        }\n        assert(Counter::count == 0);\n        ::gc::collect();\n        assert(Counter::count == 2);\n      }\n    }\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsecti6n%2Fgc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsecti6n%2Fgc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsecti6n%2Fgc/lists"}