1/*
2 * Copyright 2016-present Facebook, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#pragma once
18
19#include <atomic>
20#include <typeinfo>
21
22#include <folly/CPortability.h>
23#include <folly/Likely.h>
24#include <folly/detail/Singleton.h>
25
26namespace folly {
27namespace detail {
28
29// This internal-use-only class is used to create all leaked Meyers singletons.
30// It guarantees that only one instance of every such singleton will ever be
31// created, even when requested from different compilation units linked
32// dynamically.
33class StaticSingletonManager {
34 public:
35 template <typename T, typename Tag>
36 FOLLY_EXPORT FOLLY_ALWAYS_INLINE static T& create() {
37 static Cache cache;
38 auto const& key = typeid(TypeTuple<T, Tag>);
39 auto const v = cache.load(std::memory_order_acquire);
40 auto const p = FOLLY_LIKELY(!!v) ? v : create_(key, make<T>, cache);
41 return *static_cast<T*>(p);
42 }
43
44 private:
45 using Key = std::type_info;
46 using Make = void*();
47 using Cache = std::atomic<void*>;
48
49 template <typename T>
50 static void* make() {
51 return new T();
52 }
53
54 FOLLY_NOINLINE static void* create_(Key const& key, Make& make, Cache& cache);
55};
56
57template <typename T, typename Tag>
58FOLLY_ALWAYS_INLINE FOLLY_ATTR_VISIBILITY_HIDDEN T& createGlobal() {
59 return StaticSingletonManager::create<T, Tag>();
60}
61
62} // namespace detail
63} // namespace folly
64