{"id":21801398,"url":"https://github.com/jimmy-park/singleton","last_synced_at":"2025-07-12T23:34:55.335Z","repository":{"id":149121627,"uuid":"207273581","full_name":"jimmy-park/singleton","owner":"jimmy-park","description":"C++11/17/20 thread-safe singleton pattern using CRTP","archived":false,"fork":false,"pushed_at":"2025-07-08T12:01:42.000Z","size":105,"stargazers_count":35,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-07-08T12:52:04.152Z","etag":null,"topics":["cmake","cpp","cpp11","cpp17","cpp20","crtp","dclp","design-pattern","header-only","singleton","singleton-pattern"],"latest_commit_sha":null,"homepage":"","language":"C++","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/jimmy-park.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":"2019-09-09T09:30:49.000Z","updated_at":"2025-07-08T12:01:38.000Z","dependencies_parsed_at":null,"dependency_job_id":"6b30fd02-bc57-40c7-b839-4b707d59db99","html_url":"https://github.com/jimmy-park/singleton","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/jimmy-park/singleton","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jimmy-park%2Fsingleton","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jimmy-park%2Fsingleton/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jimmy-park%2Fsingleton/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jimmy-park%2Fsingleton/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jimmy-park","download_url":"https://codeload.github.com/jimmy-park/singleton/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jimmy-park%2Fsingleton/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265068782,"owners_count":23706530,"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":["cmake","cpp","cpp11","cpp17","cpp20","crtp","dclp","design-pattern","header-only","singleton","singleton-pattern"],"created_at":"2024-11-27T11:17:44.962Z","updated_at":"2025-07-12T23:34:55.319Z","avatar_url":"https://github.com/jimmy-park.png","language":"C++","readme":"# singleton\n\n[![CI](https://github.com/jimmy-park/singleton/actions/workflows/ci.yaml/badge.svg)](https://github.com/jimmy-park/singleton/actions/workflows/ci.yaml)\n[![CodeQL](https://github.com/jimmy-park/singleton/actions/workflows/codeql.yaml/badge.svg)](https://github.com/jimmy-park/singleton/actions/workflows/codeql.yaml)\n\nImplement thread-safe singleton classes using [Curiously Recurring Template Pattern (CRTP)](https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern)\n\n## CMake Options\n\n| Option                            | Default | Description                                           |\n| --------------------------------- | ------- | ----------------------------------------------------- |\n| `SINGLETON_INJECT_ABSTRACT_CLASS` | `OFF`   | Prevent construction of derived class at compile time |\n| `SINGLETON_INSTALL`               | `OFF`   | Install headers and CMake targets                     |\n\n## Usage\n\n### Build\n\n```sh\ncmake --list-presets all                    # List all CMake presets\ncmake --preset windows                      # Configure\ncmake --build --preset windows              # Build\nctest --preset windows                      # Test\ncmake --build --preset windows -t install   # Install\n```\n\n### Integration\n\n```CMake\ninclude(FetchContent)\n\nset(SINGLETON_INJECT_ABSTRACT_CLASS ON)\nset(SINGLETON_INSTALL ON)\n\nFetchContent_Declare(\n    singleton\n    URL https://github.com/jimmy-park/singleton/archive/main.tar.gz\n)\nFetchContent_MakeAvailable(singleton)\n\n# If you're using CPM.cmake\n# CPMAddPackage(\n#     NAME singleton\n#     URL https://github.com/jimmy-park/singleton/archive/main.tar.gz\n#     OPTIONS\n#     \"SINGLETON_INJECT_ABSTRACT_CLASS ON\"\n#     \"SINGLETON_INSTALL ON\"\n# )\n\nadd_executable(main main.cpp)\ntarget_link_libraries(main PRIVATE \n    singleton::singleton        # C++11\n    singleton::singleton-dclp   # C++17\n    singleton::singleton-atomic # C++20\n)\n```\n\n## Example\n\n### C++11\n\nRely on initialization of static local variable\n\n```cpp\n#include \u003csingleton.hpp\u003e\n\nstruct Foo : public Singleton\u003cFoo\u003e {\n    void Bar() {}\n};\n\nint main()\n{\n    // Compile error when SINGLETON_INJECT_ABSTRACT_CLASS is ON\n    // Foo foo;\n\n    Foo::GetInstance().Bar();\n}\n```\n\n### C++17\n\nImplement based on [Double-Checked Locking Pattern (DCLP)](https://en.wikipedia.org/wiki/Double-checked_locking)\n\nUse this version when you need to initialize with parameters or control the destruction order manually\n\n- C++17 features\n  - Inline static member variable\n  - If statements with initializer\n  - `std::shared_mutex`\n\n```cpp\n#include \u003csingleton_dclp.hpp\u003e\n\nclass Foo : public SingletonDclp\u003cFoo\u003e {\npublic:\n    Foo(int n) : n_ { n } {}\n    void Bar() {}\n\nprivate:\n    int n_;\n};\n\nint main()\n{\n    Foo::Construct(17);\n    Foo::GetInstance()-\u003eBar();\n    Foo::Destruct();\n}\n```\n\n#### Caveats\n\n- `GetInstance()` must be called between `Construct()` and `Destruct()`\n- Don't forget to call `Destruct()` before terminating program\n\n### C++20\n\nUse `std::atomic::wait()` to block `GetInstance()` during construction\n\n```cpp\n#include \u003csingleton_atomic.hpp\u003e\n\nclass Foo : public SingletonAtomic\u003cFoo\u003e {\npublic:\n    Foo(int n) {}\n    void Bar() {}\n};\n\nint main()\n{\n    std::jthread t { [] {\n        std::this_thread::sleep_for(std::chrono::seconds { 1 });\n        Foo::Construct(20);\n    } };                        // Construct in another thread\n    Foo::GetInstance()-\u003eBar();  // Block until construction is finished\n}\n```\n\n## Reference\n\n- [What is the curiously recurring template pattern (CRTP)?](https://stackoverflow.com/questions/4173254/what-is-the-curiously-recurring-template-pattern-crtp/4173298#4173298)\n- [C++ is Lazy: CRTP](https://www.modernescpp.com/index.php/c-is-still-lazy)\n- [Thread-Safe Initialization of a Singleton](https://www.modernescpp.com/index.php/thread-safe-initialization-of-a-singleton)\n- [Vorbrodt's C++ Blog: Singleton Pattern](https://vorbrodt.blog/2020/07/10/singleton-pattern/)\n- [Double-Checked Locking is Fixed In C++11](https://preshing.com/20130930/double-checked-locking-is-fixed-in-cpp11/)\n- [CppCon 2015: Fedor Pikus PART 1 “Live Lock-Free or Deadlock (Practical Lock-free Programming)\"](https://www.youtube.com/watch?v=lVBvHbJsg5Y)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjimmy-park%2Fsingleton","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjimmy-park%2Fsingleton","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjimmy-park%2Fsingleton/lists"}