Leak folly::SingletonVault
[folly.git] / folly / experimental / Singleton.cpp
1 /*
2  * Copyright 2014 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 #include <folly/experimental/Singleton.h>
18
19 #include <string>
20
21 namespace folly {
22
23 SingletonVault::~SingletonVault() { destroyInstances(); }
24
25 void SingletonVault::destroyInstances() {
26   {
27     RWSpinLock::ReadHolder rh(&mutex_);
28
29     CHECK_GE(singletons_.size(), creation_order_.size());
30
31     for (auto type_iter = creation_order_.rbegin();
32          type_iter != creation_order_.rend();
33          ++type_iter) {
34       auto type = *type_iter;
35       auto it = singletons_.find(type);
36       CHECK(it != singletons_.end());
37       auto& entry = it->second;
38       std::lock_guard<std::mutex> entry_guard(entry->mutex);
39       if (entry->instance.use_count() > 1) {
40         LOG(ERROR) << "Singleton of type " << type.name() << " has a living "
41                    << "reference at destroyInstances time; beware! Raw pointer "
42                    << "is " << entry->instance.get() << " with use_count of "
43                    << entry->instance.use_count();
44       }
45       entry->instance.reset();
46       entry->state = SingletonEntryState::Dead;
47       entry->state_condvar.notify_all();
48     }
49   }
50
51   {
52     RWSpinLock::WriteHolder wh(&mutex_);
53     creation_order_.clear();
54   }
55 }
56
57 SingletonVault* SingletonVault::singleton() {
58   static SingletonVault* vault = new SingletonVault();
59   return vault;
60 }
61
62 namespace {
63
64 class SingletonVaultDestructor {
65  public:
66   ~SingletonVaultDestructor() {
67     SingletonVault::singleton()->destroyInstances();
68   }
69 };
70
71 SingletonVaultDestructor singletonVaultDestructor;
72
73 }
74
75 }