Fix double definition for templated folly::Singletons
authorAndrii Grynenko <andrii@fb.com>
Wed, 24 Feb 2016 03:49:07 +0000 (19:49 -0800)
committerfacebook-github-bot-4 <folly-bot@fb.com>
Wed, 24 Feb 2016 04:20:26 +0000 (20:20 -0800)
Summary: Allow createGlobal() to create dependent objects.

Reviewed By: yfeldblum

Differential Revision: D2963111

fb-gh-sync-id: 8e4da48a7a1000934963396b423e8eff98a8aade
shipit-source-id: 8e4da48a7a1000934963396b423e8eff98a8aade

folly/Singleton.h

index e083e35b6d5dae5ed6c908d576d6999a018514a7..bb04862d5c9be8185634d7ac4a134598072db47a 100644 (file)
@@ -170,14 +170,23 @@ class StaticSingletonManager {
 
   template <typename T, typename Tag, typename F>
   inline T* create(F&& creator) {
-    std::lock_guard<std::mutex> lg(mutex_);
+    auto& entry = [&]() mutable -> Entry<T>& {
+      std::lock_guard<std::mutex> lg(mutex_);
 
-    auto& id = typeid(TypePair<T, Tag>);
-    auto& ptr = reinterpret_cast<T*&>(map_[id]);
-    if (!ptr) {
-      ptr = creator();
+      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 ptr;
+    return entry.ptr;
   }
 
  private:
@@ -186,6 +195,12 @@ class StaticSingletonManager {
 
   StaticSingletonManager() {}
 
+  template <typename T>
+  struct Entry {
+    T* ptr{nullptr};
+    std::mutex mutex;
+  };
+
   std::unordered_map<std::type_index, intptr_t> map_;
   std::mutex mutex_;
 };