| 77 | // |
| 78 | // LSAN COMPATIBILITY: Uses __lsan::ScopedDisabler to prevent false positives. |
| 79 | template <typename T, int N = 0> class SingletonShared { |
| 80 | public: |
| 81 | static T &instance() FL_NOEXCEPT { |
| 82 | // Check the process-wide registry first (handles cross-DLL sharing). |
| 83 | // FL_PRETTY_FUNCTION produces a unique string per template instantiation |
| 84 | // (includes template parameters in the signature). |
| 85 | void* existing = detail::singleton_registry_get(FL_PRETTY_FUNCTION); |
| 86 | if (existing) { |
| 87 | return *static_cast<T*>(existing); |
| 88 | } |
| 89 | // First time for this type — create and register |
| 90 | T* ptr = instanceInner(); |
| 91 | detail::singleton_registry_set(FL_PRETTY_FUNCTION, ptr); |
| 92 | return *ptr; |
| 93 | } |
| 94 | |
| 95 | static T *instanceRef() FL_NOEXCEPT { return &instance(); } |
| 96 | |
| 97 | SingletonShared(const SingletonShared &) FL_NOEXCEPT = delete; |
| 98 | SingletonShared &operator=(const SingletonShared &) FL_NOEXCEPT = delete; |
| 99 | |
| 100 | private: |
| 101 | SingletonShared() FL_NOEXCEPT = default; |
| 102 | ~SingletonShared() FL_NOEXCEPT = default; |
| 103 | |
| 104 | static T* instanceInner() FL_NOEXCEPT { |
| 105 | // Aligned char buffer storage — never destroyed |
| 106 | struct FL_ALIGN_AS_T(alignof(T)) AlignedStorage { |
| 107 | char data[sizeof(T)]; |
| 108 | }; |
| 109 | |
| 110 | static AlignedStorage storage; |
| 111 | |
| 112 | #if FL_HAS_SANITIZER_LSAN |
| 113 | __lsan::ScopedDisabler disabler; // Ignore all allocations in this scope |
| 114 | #endif |
| 115 | |
| 116 | T* ptr = new (&storage.data) T(); |
| 117 | return ptr; |
| 118 | } |
| 119 | }; |
| 120 | |
| 121 | // Thread-local singleton — combines Singleton and ThreadLocal patterns. |
| 122 | // Each thread gets its own T instance, but the ThreadLocal<T> container itself |
nothing calls this directly
no test coverage detected