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 | |
26 | namespace folly { |
27 | namespace 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. |
33 | class 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 | |
57 | template <typename T, typename Tag> |
58 | FOLLY_ALWAYS_INLINE FOLLY_ATTR_VISIBILITY_HIDDEN T& createGlobal() { |
59 | return StaticSingletonManager::create<T, Tag>(); |
60 | } |
61 | |
62 | } // namespace detail |
63 | } // namespace folly |
64 | |