Commit ec8d84ff authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook Github Bot

A small inline fast path for StaticSingletonManager::create

Summary: [Folly] A small inline fast path for `StaticSingletonManager::create`.

Reviewed By: andriigrynenko

Differential Revision: D13114824

fbshipit-source-id: b72b6066b7ff5401e37e75aa1c8102e6536e9740
parent 592b2621
......@@ -27,9 +27,7 @@ SingletonHolder<T>& SingletonHolder<T>::singleton() {
{typeid(T), typeid(Tag)},
*SingletonVault::singleton<VaultTag>()) {}
};
/* library-local */ static auto entry =
createGlobal<SingletonHolderImpl, void>();
return *entry;
return *createGlobal<SingletonHolderImpl, void>();
}
[[noreturn]] void singletonWarnDoubleRegistrationAndAbort(
......
......@@ -500,17 +500,14 @@ class SingletonVault {
// tests only.
template <typename VaultTag = detail::DefaultTag>
static SingletonVault* singleton() {
/* library-local */ static auto vault =
detail::createGlobal<SingletonVault, VaultTag>();
return vault;
return detail::createGlobal<SingletonVault, VaultTag>();
}
typedef std::string (*StackTraceGetterPtr)();
static std::atomic<StackTraceGetterPtr>& stackTraceGetter() {
/* library-local */ static auto stackTraceGetterPtr = detail::
createGlobal<std::atomic<StackTraceGetterPtr>, SingletonVault>();
return *stackTraceGetterPtr;
struct Result : std::atomic<StackTraceGetterPtr> {};
return *detail::createGlobal<Result, void>();
}
void setType(Type type) {
......@@ -746,8 +743,7 @@ class LeakySingleton {
};
static Entry& entryInstance() {
/* library-local */ static auto entry = detail::createGlobal<Entry, Tag>();
return *entry;
return *detail::createGlobal<Entry, Tag>();
}
static T& instance() {
......
......@@ -132,9 +132,8 @@ class SingletonThreadLocal {
SingletonThreadLocal() = delete;
FOLLY_EXPORT FOLLY_NOINLINE static WrapperTL& getWrapperTL() {
static auto& entry = *detail::createGlobal<WrapperTL, Tag>();
return entry;
FOLLY_ALWAYS_INLINE static WrapperTL& getWrapperTL() {
return *detail::createGlobal<WrapperTL, Tag>();
}
FOLLY_NOINLINE static Wrapper& getWrapper() {
......
......@@ -27,16 +27,24 @@ namespace {
class StaticSingletonManagerImpl {
public:
void* create(std::type_info const& key, void* (*make)()) {
auto& e = entry(key);
std::lock_guard<std::mutex> lock(e.mutex);
return e.ptr ? e.ptr : (e.ptr = make());
using Make = void*();
using Cache = std::atomic<void*>;
void* create(std::type_info const& key, Make& make, Cache& cache) {
auto const ptr = entry(key).get(make);
cache.store(ptr, std::memory_order_release);
return ptr;
}
private:
struct Entry {
void* ptr{};
std::mutex mutex;
void* get(Make& make) {
std::lock_guard<std::mutex> lock(mutex);
return ptr ? ptr : (ptr = make());
}
};
Entry& entry(std::type_info const& key) {
......@@ -51,10 +59,13 @@ class StaticSingletonManagerImpl {
} // namespace
void* StaticSingletonManager::create_(Key const& key, Make* make) {
void* StaticSingletonManager::create_(
Key const& key,
Make& make,
Cache& cache) {
// This Leaky Meyers Singleton must always live in the .cpp file.
static auto& instance = *new StaticSingletonManagerImpl();
return instance.create(key, make);
return instance.create(key, make, cache);
}
} // namespace detail
......
......@@ -16,9 +16,11 @@
#pragma once
#include <atomic>
#include <typeinfo>
#include <folly/CPortability.h>
#include <folly/Likely.h>
namespace folly {
namespace detail {
......@@ -30,9 +32,12 @@ namespace detail {
class StaticSingletonManager {
public:
template <typename T, typename Tag>
FOLLY_ALWAYS_INLINE FOLLY_ATTR_VISIBILITY_HIDDEN static T* create() {
FOLLY_EXPORT FOLLY_ALWAYS_INLINE static T* create() {
static Cache cache;
auto const& key = typeid(TypePair<T, Tag>);
return static_cast<T*>(create_(key, &Creator<T>::create));
auto const v = cache.load(std::memory_order_acquire);
auto const p = FOLLY_LIKELY(!!v) ? v : create_(key, make<T>, cache);
return static_cast<T*>(p);
}
private:
......@@ -41,15 +46,14 @@ class StaticSingletonManager {
using Key = std::type_info;
using Make = void*();
using Cache = std::atomic<void*>;
template <typename T>
struct Creator {
static void* create() {
return new T();
}
};
static void* make() {
return new T();
}
FOLLY_NOINLINE static void* create_(Key const& key, Make* make);
FOLLY_NOINLINE static void* create_(Key const& key, Make& make, Cache& cache);
};
template <typename T, typename Tag>
......
......@@ -93,7 +93,7 @@ ThreadEntryList* StaticMetaBase::getThreadEntryList() {
pthread_key_t pthreadKey_;
};
static auto instance = detail::createGlobal<PthreadKey, void>();
auto instance = detail::createGlobal<PthreadKey, void>();
ThreadEntryList* threadEntryList =
static_cast<ThreadEntryList*>(pthread_getspecific(instance->get()));
......
......@@ -428,9 +428,7 @@ struct StaticMeta final : StaticMetaBase {
static StaticMeta<Tag, AccessMode>& instance() {
// Leak it on exit, there's only one per process and we don't have to
// worry about synchronization with exiting threads.
/* library-local */ static auto instance =
detail::createGlobal<StaticMeta<Tag, AccessMode>, void>();
return *instance;
return *detail::createGlobal<StaticMeta<Tag, AccessMode>, void>();
}
FOLLY_EXPORT FOLLY_ALWAYS_INLINE static ElementWrapper& get(EntryID* ent) {
......
......@@ -21,6 +21,10 @@
namespace folly {
namespace detail {
extern "C" int* check() {
return createGlobal<int, void>();
}
struct StaticSingletonManagerTest : public testing::Test {};
template <typename T>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment