0

愚蠢的 SingletonThreadLocal 类使用两个“c11 thread_local”和一个“ThreadLocal”来支持快速访问和销毁依赖问题。

但我无法理解“thread_local 和 ThreadLocal”的破坏顺序。

  FOLLY_EXPORT FOLLY_ALWAYS_INLINE static T& get() {
    if (kIsMobile) {
      return getWrapper();
    }
    static thread_local LocalCache cache;
    return FOLLY_LIKELY(!!cache.cache) ? *cache.cache : getSlow(cache);
  }
  FOLLY_NOINLINE static Wrapper& getSlow(LocalCache& cache) {
    if (threadlocal_detail::StaticMetaBase::dying()) {
      return getWrapper();
    }
    static thread_local LocalLifetime lifetime;
    lifetime.track(cache); // idempotent
    return FOLLY_LIKELY(!!cache.cache) ? *cache.cache : getWrapper();
  }
  struct LocalLifetime {
    ~LocalLifetime() {
      auto& wrapper = getWrapper();
      auto& lifetimes = wrapper.lifetimes[this]; //1. thread wrapper may be destructed.
      for (auto cache : lifetimes) {
        auto const it = wrapper.caches.find(cache);
        if (!--it->second) {
          wrapper.caches.erase(it);
          cache->cache = nullptr;
        }
      }
      wrapper.lifetimes.erase(this);
    }
   ...
   }
  struct Wrapper {
      ~Wrapper() {
      for (auto& kvp : caches) { //cache may be destruct
        kvp.first->cache = nullptr; //2. thread cache maybe destructed.
      }
    }
  }

请查看评论 1、2. LocalLifetime LocalCache 的破坏顺序,而 ThreadLocal 是未定义的,代码可能会访问被破坏的内存,令人惊讶。

4

0 回答 0