#include <folly/Demangle.h>
#include <folly/Executor.h>
#include <folly/experimental/ReadMostlySharedPtr.h>
+#include <folly/detail/StaticSingletonManager.h>
#include <algorithm>
#include <atomic>
namespace detail {
-// This internal-use-only class is used to create all leaked Meyers singletons.
-// It guarantees that only one instance of every such singleton will ever be
-// created, even when requested from different compilation units linked
-// dynamically.
-class StaticSingletonManager {
- public:
- static StaticSingletonManager& instance();
-
- template <typename T, typename Tag, typename F>
- inline T* create(F&& creator) {
- auto& entry = [&]() mutable -> Entry<T>& {
- std::lock_guard<std::mutex> lg(mutex_);
-
- auto& id = typeid(TypePair<T, Tag>);
- auto& entryPtr = reinterpret_cast<Entry<T>*&>(map_[id]);
- if (!entryPtr) {
- entryPtr = new Entry<T>();
- }
- return *entryPtr;
- }();
-
- std::lock_guard<std::mutex> lg(entry.mutex);
-
- if (!entry.ptr) {
- entry.ptr = creator();
- }
- return entry.ptr;
- }
-
- private:
- template <typename A, typename B>
- class TypePair {};
-
- StaticSingletonManager() {}
-
- template <typename T>
- struct Entry {
- T* ptr{nullptr};
- std::mutex mutex;
- };
-
- std::unordered_map<std::type_index, intptr_t> map_;
- std::mutex mutex_;
-};
-
-template <typename T, typename Tag, typename F>
-inline T* createGlobal(F&& creator) {
- return StaticSingletonManager::instance().create<T, Tag>(
- std::forward<F>(creator));
-}
-
-template <typename T, typename Tag>
-inline T* createGlobal() {
- return createGlobal<T, Tag>([]() { return new T(); });
-}
-
struct DefaultTag {};
// A TypeDescriptor is the unique handle for a given singleton. It is
// SingletonHolders.
class SingletonHolderBase {
public:
+ explicit SingletonHolderBase(TypeDescriptor typeDesc) : type_(typeDesc) {}
virtual ~SingletonHolderBase() = default;
- virtual TypeDescriptor type() = 0;
+ TypeDescriptor type() const {
+ return type_;
+ }
virtual bool hasLiveInstance() = 0;
virtual void createInstance() = 0;
virtual bool creationStarted() = 0;
+ virtual void preDestroyInstance(ReadMostlyMainPtrDeleter<>&) = 0;
virtual void destroyInstance() = 0;
- protected:
- static constexpr std::chrono::seconds kDestroyWaitTime{5};
+ private:
+ TypeDescriptor type_;
};
// An actual instance of a singleton, tracking the instance itself,
void registerSingleton(CreateFunc c, TeardownFunc t);
void registerSingletonMock(CreateFunc c, TeardownFunc t);
- virtual TypeDescriptor type() override;
virtual bool hasLiveInstance() override;
virtual void createInstance() override;
virtual bool creationStarted() override;
+ virtual void preDestroyInstance(ReadMostlyMainPtrDeleter<>&) override;
virtual void destroyInstance() override;
private:
Living,
};
- TypeDescriptor type_;
SingletonVault& vault_;
// mutex protects the entire entry during construction/destruction
// holds a ReadMostlyMainPtr to singleton instance, set when state is changed
// from Dead to Living. Reset when state is changed from Living to Dead.
folly::ReadMostlyMainPtr<T> instance_;
+ // used to release all ReadMostlyMainPtrs at once
+ folly::ReadMostlySharedPtr<T> instance_copy_;
// 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
return *stackTraceGetterPtr;
}
+ void setType(Type type) {
+ type_ = type;
+ }
+
private:
template <typename T>
friend struct detail::SingletonHolder;