2 * Copyright 2016 Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 #include <unordered_map>
26 // This internal-use-only class is used to create all leaked Meyers singletons.
27 // It guarantees that only one instance of every such singleton will ever be
28 // created, even when requested from different compilation units linked
30 class StaticSingletonManager {
32 static StaticSingletonManager& instance();
34 template <typename T, typename Tag, typename F>
35 inline T* create(F&& creator) {
36 auto& entry = [&]() mutable -> Entry<T>& {
37 std::lock_guard<std::mutex> lg(mutex_);
39 auto& id = typeid(TypePair<T, Tag>);
40 auto& entryPtr = map_[id];
42 entryPtr = new Entry<T>();
44 assert(dynamic_cast<Entry<T>*>(entryPtr) != nullptr);
45 return *static_cast<Entry<T>*>(entryPtr);
48 std::lock_guard<std::mutex> lg(entry.mutex);
51 entry.ptr = creator();
57 template <typename A, typename B>
60 StaticSingletonManager() {}
67 struct Entry : public EntryIf {
72 std::unordered_map<std::type_index, EntryIf*> map_;
76 template <typename T, typename Tag, typename F>
77 inline T* createGlobal(F&& creator) {
78 return StaticSingletonManager::instance().create<T, Tag>(
79 std::forward<F>(creator));
82 template <typename T, typename Tag>
83 inline T* createGlobal() {
84 return createGlobal<T, Tag>([]() { return new T(); });