/*
- * Copyright 2016 Facebook, Inc.
+ * Copyright 2016-present Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#pragma once
-#include <folly/ThreadLocal.h>
#include <folly/Singleton.h>
+#include <folly/ThreadLocal.h>
namespace folly {
+// SingletonThreadLocal
+//
+// This class can help you implement a per-thread leaky-singleton model within
+// your application. Please read the usage block at the top of Singleton.h as
+// the recommendations there are also generally applicable to this class.
+//
+// When we say this is "leaky" we mean that the T instances held by a
+// SingletonThreadLocal<T> will survive until their owning thread exits,
+// regardless of the lifetime of the singleton object holding them. That
+// means that they can be safely used during process shutdown, and
+// that they can also be safely used in an application that spawns many
+// temporary threads throughout its life.
+//
+// Keywords to help people find this class in search:
+// Thread Local Singleton ThreadLocalSingleton
template <typename T, typename Tag = detail::DefaultTag>
class SingletonThreadLocal {
public:
SingletonThreadLocal() : SingletonThreadLocal([]() { return new T(); }) {}
- explicit SingletonThreadLocal(CreateFunc createFunc)
- : singleton_([createFunc = std::move(createFunc)]() mutable {
- return new ThreadLocalT([createFunc =
- std::move(createFunc)]() mutable {
- return new Wrapper(std::unique_ptr<T>(createFunc()));
+ template <typename Create>
+ FOLLY_NOINLINE explicit SingletonThreadLocal(Create create)
+ : singleton_([create = std::move(create)]() mutable {
+ return new ThreadLocalT([create = std::move(create)]() mutable {
+ return new Wrapper(std::unique_ptr<T>(create()));
});
}) {}
- static T& get() {
+ FOLLY_ALWAYS_INLINE static T& get() {
#ifdef FOLLY_TLS
- if (UNLIKELY(*localPtr() == nullptr)) {
- *localPtr() = &(**SingletonT::get());
- }
-
- return **localPtr();
+ return *localPtr() ? **localPtr() : *(*localPtr() = &getSlow());
#else
return **SingletonT::get();
#endif
}
private:
+ FOLLY_NOINLINE static T& getSlow() {
+ return **SingletonT::get();
+ }
+
#ifdef FOLLY_TLS
- static T** localPtr() {
+ FOLLY_ALWAYS_INLINE static T** localPtr() {
static FOLLY_TLS T* localPtr = nullptr;
return &localPtr;
}
SingletonT singleton_;
};
-}
+} // namespace folly