template <typename T>
T* SingletonHolder<T>::get() {
- if (LIKELY(state_ == SingletonHolderState::Living)) {
+ if (LIKELY(state_.load(std::memory_order_acquire) ==
+ SingletonHolderState::Living)) {
return instance_ptr_;
}
createInstance();
template <typename T>
std::weak_ptr<T> SingletonHolder<T>::get_weak() {
- if (UNLIKELY(state_ != SingletonHolderState::Living)) {
+ if (UNLIKELY(state_.load(std::memory_order_acquire) !=
+ SingletonHolderState::Living)) {
createInstance();
}
return instance_weak_;
}
+template <typename T>
+std::shared_ptr<T> SingletonHolder<T>::try_get() {
+ if (UNLIKELY(state_.load(std::memory_order_acquire) !=
+ SingletonHolderState::Living)) {
+ createInstance();
+ }
+
+ return instance_weak_.lock();
+}
+
template <typename T>
TypeDescriptor SingletonHolder<T>::type() {
return type_;
inline T* get();
inline std::weak_ptr<T> get_weak();
+ inline std::shared_ptr<T> try_get();
void registerSingleton(CreateFunc c, TeardownFunc t);
void registerSingletonMock(CreateFunc c, TeardownFunc t);
// Avoid holding these shared_ptrs beyond the scope of a function;
// don't put them in member variables, always use try_get() instead
static std::shared_ptr<T> try_get() {
- auto ret = get_weak().lock();
+ auto ret = getEntry().try_get();
if (!ret) {
LOG(DFATAL) <<
"folly::Singleton<" << getEntry().type().name() <<
int val = 0;
};
-BENCHMARK(NormalSingleton, n) {
- for (size_t i = 0; i < n; ++i) {
+void run4Threads(std::function<void()> f) {
+ std::vector<std::thread> threads;
+ for (size_t i = 0; i < 4; ++ i) {
+ threads.emplace_back(f);
+ }
+ for (auto& thread : threads) {
+ thread.join();
+ }
+}
+
+void normalSingleton(size_t n) {
+ for (size_t i = 0; i < n; ++ i) {
doNotOptimizeAway(getNormalSingleton());
}
}
-BENCHMARK_RELATIVE(MeyersSingleton, n) {
+BENCHMARK(NormalSingleton, n) {
+ normalSingleton(n);
+}
+
+BENCHMARK(NormalSingleton4Threads, n) {
+ run4Threads([=]() {
+ normalSingleton(n);
+ });
+}
+
+void meyersSingleton(size_t n) {
for (size_t i = 0; i < n; ++i) {
doNotOptimizeAway(getMeyersSingleton());
}
}
+
+BENCHMARK_RELATIVE(MeyersSingleton, n) {
+ meyersSingleton(n);
+}
+
+BENCHMARK_RELATIVE(MeyersSingleton4Threads, n) {
+ run4Threads([=]() {
+ meyersSingleton(n);
+ });
+}
+
struct BenchmarkTag {};
template <typename T, typename Tag = detail::DefaultTag>
using SingletonBenchmark = Singleton <T, Tag, BenchmarkTag>;
struct GetTag{};
+struct GetSharedTag{};
struct GetWeakTag{};
SingletonBenchmark<BenchmarkSingleton, GetTag> benchmark_singleton_get;
+SingletonBenchmark<BenchmarkSingleton, GetSharedTag>
+benchmark_singleton_get_shared;
SingletonBenchmark<BenchmarkSingleton, GetWeakTag> benchmark_singleton_get_weak;
-BENCHMARK_RELATIVE(FollySingleton, n) {
+void follySingletonRaw(size_t n) {
+ for (size_t i = 0; i < n; ++i) {
+ SingletonBenchmark<BenchmarkSingleton, GetTag>::get();
+ }
+}
+
+BENCHMARK_RELATIVE(FollySingletonRaw, n) {
+ follySingletonRaw(n);
+}
+
+BENCHMARK_RELATIVE(FollySingletonRaw4Threads, n) {
+ run4Threads([=]() {
+ follySingletonRaw(n);
+ });
+}
+
+void follySingletonSharedPtr(size_t n) {
for (size_t i = 0; i < n; ++i) {
- SingletonBenchmark<BenchmarkSingleton, GetTag>::try_get();
+ SingletonBenchmark<BenchmarkSingleton, GetSharedTag>::try_get();
}
}
-BENCHMARK_RELATIVE(FollySingletonWeak, n) {
+BENCHMARK_RELATIVE(FollySingletonSharedPtr, n) {
+ follySingletonSharedPtr(n);
+}
+
+BENCHMARK_RELATIVE(FollySingletonSharedPtr4Threads, n) {
+ run4Threads([=]() {
+ follySingletonSharedPtr(n);
+ });
+}
+
+void follySingletonWeakPtr(size_t n) {
for (size_t i = 0; i < n; ++i) {
SingletonBenchmark<BenchmarkSingleton, GetWeakTag>::get_weak();
}
}
+BENCHMARK_RELATIVE(FollySingletonWeakPtr, n) {
+ follySingletonWeakPtr(n);
+}
+
+BENCHMARK_RELATIVE(FollySingletonWeakPtr4Threads, n) {
+ run4Threads([=]() {
+ follySingletonWeakPtr(n);
+ });
+}
+
int main(int argc, char* argv[]) {
testing::InitGoogleTest(&argc, argv);
google::InitGoogleLogging(argv[0]);