+
+enum class SingletonEntryState {
+ Dead,
+ Living,
+};
+
+// An actual instance of a singleton, tracking the instance itself,
+// its state as described above, and the create and teardown
+// functions.
+struct SingletonEntry {
+ typedef std::function<void(void*)> TeardownFunc;
+ typedef std::function<void*(void)> CreateFunc;
+
+ SingletonEntry(CreateFunc c, TeardownFunc t) :
+ create(std::move(c)), teardown(std::move(t)) {}
+
+ // mutex protects the entire entry during construction/destruction
+ std::mutex mutex;
+
+ // State of the singleton entry. If state is Living, instance_ptr and
+ // instance_weak can be safely accessed w/o synchronization.
+ std::atomic<SingletonEntryState> state{SingletonEntryState::Dead};
+
+ // the thread creating the singleton (only valid while creating an object)
+ std::thread::id creating_thread;
+
+ // The singleton itself and related functions.
+
+ // holds a shared_ptr to singleton instance, set when state is changed from
+ // Dead to Living. Reset when state is changed from Living to Dead.
+ std::shared_ptr<void> instance;
+ // weak_ptr to the singleton instance, set when state is changed from Dead
+ // to Living. We never write to this object after initialization, so it is
+ // safe to read it from different threads w/o synchronization if we know
+ // that state is set to Living
+ std::weak_ptr<void> instance_weak;
+ void* instance_ptr = nullptr;
+ CreateFunc create = nullptr;
+ TeardownFunc teardown = nullptr;
+
+ SingletonEntry(const SingletonEntry&) = delete;
+ SingletonEntry& operator=(const SingletonEntry&) = delete;
+ SingletonEntry& operator=(SingletonEntry&&) = delete;
+ SingletonEntry(SingletonEntry&&) = delete;
+};
+