https://github.com/jimmy-park/singleton
C++11/17/20 thread-safe singleton pattern using CRTP
https://github.com/jimmy-park/singleton
cmake cpp cpp11 cpp17 cpp20 crtp dclp design-pattern header-only singleton singleton-pattern
Last synced: 3 months ago
JSON representation
C++11/17/20 thread-safe singleton pattern using CRTP
- Host: GitHub
- URL: https://github.com/jimmy-park/singleton
- Owner: jimmy-park
- License: mit
- Created: 2019-09-09T09:30:49.000Z (about 6 years ago)
- Default Branch: main
- Last Pushed: 2025-07-08T12:01:42.000Z (3 months ago)
- Last Synced: 2025-07-08T12:52:04.152Z (3 months ago)
- Topics: cmake, cpp, cpp11, cpp17, cpp20, crtp, dclp, design-pattern, header-only, singleton, singleton-pattern
- Language: C++
- Homepage:
- Size: 103 KB
- Stars: 35
- Watchers: 2
- Forks: 2
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# singleton
[](https://github.com/jimmy-park/singleton/actions/workflows/ci.yaml)
[](https://github.com/jimmy-park/singleton/actions/workflows/codeql.yaml)Implement thread-safe singleton classes using [Curiously Recurring Template Pattern (CRTP)](https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern)
## CMake Options
| Option | Default | Description |
| --------------------------------- | ------- | ----------------------------------------------------- |
| `SINGLETON_INJECT_ABSTRACT_CLASS` | `OFF` | Prevent construction of derived class at compile time |
| `SINGLETON_INSTALL` | `OFF` | Install headers and CMake targets |## Usage
### Build
```sh
cmake --list-presets all # List all CMake presets
cmake --preset windows # Configure
cmake --build --preset windows # Build
ctest --preset windows # Test
cmake --build --preset windows -t install # Install
```### Integration
```CMake
include(FetchContent)set(SINGLETON_INJECT_ABSTRACT_CLASS ON)
set(SINGLETON_INSTALL ON)FetchContent_Declare(
singleton
URL https://github.com/jimmy-park/singleton/archive/main.tar.gz
)
FetchContent_MakeAvailable(singleton)# If you're using CPM.cmake
# CPMAddPackage(
# NAME singleton
# URL https://github.com/jimmy-park/singleton/archive/main.tar.gz
# OPTIONS
# "SINGLETON_INJECT_ABSTRACT_CLASS ON"
# "SINGLETON_INSTALL ON"
# )add_executable(main main.cpp)
target_link_libraries(main PRIVATE
singleton::singleton # C++11
singleton::singleton-dclp # C++17
singleton::singleton-atomic # C++20
)
```## Example
### C++11
Rely on initialization of static local variable
```cpp
#includestruct Foo : public Singleton {
void Bar() {}
};int main()
{
// Compile error when SINGLETON_INJECT_ABSTRACT_CLASS is ON
// Foo foo;Foo::GetInstance().Bar();
}
```### C++17
Implement based on [Double-Checked Locking Pattern (DCLP)](https://en.wikipedia.org/wiki/Double-checked_locking)
Use this version when you need to initialize with parameters or control the destruction order manually
- C++17 features
- Inline static member variable
- If statements with initializer
- `std::shared_mutex````cpp
#includeclass Foo : public SingletonDclp {
public:
Foo(int n) : n_ { n } {}
void Bar() {}private:
int n_;
};int main()
{
Foo::Construct(17);
Foo::GetInstance()->Bar();
Foo::Destruct();
}
```#### Caveats
- `GetInstance()` must be called between `Construct()` and `Destruct()`
- Don't forget to call `Destruct()` before terminating program### C++20
Use `std::atomic::wait()` to block `GetInstance()` during construction
```cpp
#includeclass Foo : public SingletonAtomic {
public:
Foo(int n) {}
void Bar() {}
};int main()
{
std::jthread t { [] {
std::this_thread::sleep_for(std::chrono::seconds { 1 });
Foo::Construct(20);
} }; // Construct in another thread
Foo::GetInstance()->Bar(); // Block until construction is finished
}
```## Reference
- [What is the curiously recurring template pattern (CRTP)?](https://stackoverflow.com/questions/4173254/what-is-the-curiously-recurring-template-pattern-crtp/4173298#4173298)
- [C++ is Lazy: CRTP](https://www.modernescpp.com/index.php/c-is-still-lazy)
- [Thread-Safe Initialization of a Singleton](https://www.modernescpp.com/index.php/thread-safe-initialization-of-a-singleton)
- [Vorbrodt's C++ Blog: Singleton Pattern](https://vorbrodt.blog/2020/07/10/singleton-pattern/)
- [Double-Checked Locking is Fixed In C++11](https://preshing.com/20130930/double-checked-locking-is-fixed-in-cpp11/)
- [CppCon 2015: Fedor Pikus PART 1 “Live Lock-Free or Deadlock (Practical Lock-free Programming)"](https://www.youtube.com/watch?v=lVBvHbJsg5Y)