| 80 | // so it's not a good idea for the creator to block on something. |
| 81 | template <typename T> |
| 82 | std::shared_ptr<T> Get( |
| 83 | const std::string &name, |
| 84 | std::function<std::shared_ptr<T>()> creator = DefaultConstructor<T>) { |
| 85 | SharedObjectKey key = std::make_pair(std::type_index(typeid(T)), name); |
| 86 | |
| 87 | static std::recursive_mutex mutex; |
| 88 | std::lock_guard<decltype(mutex)> lock(mutex); |
| 89 | |
| 90 | auto it = obj_map_.find(key); |
| 91 | if (it != obj_map_.end()) { |
| 92 | // Found, but check if the weak pointer has become stale. |
| 93 | if (auto ret = it->second.lock()) { |
| 94 | // Fresh. Convert from shared_ptr<void> to shared_ptr<T> and return |
| 95 | return std::static_pointer_cast<T>(ret); |
| 96 | } |
| 97 | } |
| 98 | |
| 99 | // "creator" returns an empty shared_ptr if object allocation |
| 100 | // failed or no object should be newly made. |
| 101 | std::shared_ptr<T> new_object = creator(); |
| 102 | if (new_object) { |
| 103 | obj_map_[key] = std::weak_ptr<T>(new_object); |
| 104 | } |
| 105 | |
| 106 | return new_object; |
| 107 | } |
| 108 | |
| 109 | // If no object with the specified type&name is found, this method does not |
| 110 | // create a new one. |