Fix a potential deadlock when opening a realm
This commit is contained in:
parent
e87a507223
commit
c3a9489b02
|
@ -24,6 +24,11 @@
|
||||||
using namespace realm;
|
using namespace realm;
|
||||||
using namespace realm::_impl;
|
using namespace realm::_impl;
|
||||||
|
|
||||||
|
struct realm::_impl::CachedRealm {
|
||||||
|
std::weak_ptr<Realm> realm;
|
||||||
|
std::thread::id thread_id;
|
||||||
|
};
|
||||||
|
|
||||||
static std::mutex s_coordinator_mutex;
|
static std::mutex s_coordinator_mutex;
|
||||||
static std::map<std::string, std::weak_ptr<RealmCoordinator>> s_coordinators_per_path;
|
static std::map<std::string, std::weak_ptr<RealmCoordinator>> s_coordinators_per_path;
|
||||||
|
|
||||||
|
@ -86,11 +91,11 @@ std::shared_ptr<Realm> RealmCoordinator::get_realm(Realm::Config config)
|
||||||
|
|
||||||
auto thread_id = std::this_thread::get_id();
|
auto thread_id = std::this_thread::get_id();
|
||||||
if (config.cache) {
|
if (config.cache) {
|
||||||
for (auto& weakRealm : m_cached_realms) {
|
for (auto& cachedRealm : m_cached_realms) {
|
||||||
|
if (cachedRealm.thread_id == thread_id) {
|
||||||
// can be null if we jumped in between ref count hitting zero and
|
// can be null if we jumped in between ref count hitting zero and
|
||||||
// unregister_realm() getting the lock
|
// unregister_realm() getting the lock
|
||||||
if (auto realm = weakRealm.lock()) {
|
if (auto realm = cachedRealm.realm.lock()) {
|
||||||
if (realm->thread_id() == thread_id) {
|
|
||||||
return realm;
|
return realm;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,7 +108,7 @@ std::shared_ptr<Realm> RealmCoordinator::get_realm(Realm::Config config)
|
||||||
m_notifier->add_realm(realm.get());
|
m_notifier->add_realm(realm.get());
|
||||||
}
|
}
|
||||||
if (config.cache) {
|
if (config.cache) {
|
||||||
m_cached_realms.push_back(realm);
|
m_cached_realms.push_back({realm, thread_id});
|
||||||
}
|
}
|
||||||
return realm;
|
return realm;
|
||||||
}
|
}
|
||||||
|
@ -135,7 +140,7 @@ void RealmCoordinator::unregister_realm(Realm* realm)
|
||||||
m_notifier->remove_realm(realm);
|
m_notifier->remove_realm(realm);
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < m_cached_realms.size(); ++i) {
|
for (size_t i = 0; i < m_cached_realms.size(); ++i) {
|
||||||
if (m_cached_realms[i].expired()) {
|
if (m_cached_realms[i].realm.expired()) {
|
||||||
if (i + 1 < m_cached_realms.size()) {
|
if (i + 1 < m_cached_realms.size()) {
|
||||||
m_cached_realms[i] = std::move(m_cached_realms.back());
|
m_cached_realms[i] = std::move(m_cached_realms.back());
|
||||||
}
|
}
|
||||||
|
@ -159,7 +164,7 @@ void RealmCoordinator::clear_cache()
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& cached_realm : coordinator->m_cached_realms) {
|
for (auto& cached_realm : coordinator->m_cached_realms) {
|
||||||
if (auto realm = cached_realm.lock()) {
|
if (auto realm = cached_realm.realm.lock()) {
|
||||||
realms_to_close.push_back(realm);
|
realms_to_close.push_back(realm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
namespace realm {
|
namespace realm {
|
||||||
namespace _impl {
|
namespace _impl {
|
||||||
class ExternalCommitHelper;
|
class ExternalCommitHelper;
|
||||||
|
struct CachedRealm;
|
||||||
|
|
||||||
// RealmCoordinator manages the weak cache of Realm instances and communication
|
// RealmCoordinator manages the weak cache of Realm instances and communication
|
||||||
// between per-thread Realm instances for a given file
|
// between per-thread Realm instances for a given file
|
||||||
|
@ -66,7 +67,7 @@ private:
|
||||||
Realm::Config m_config;
|
Realm::Config m_config;
|
||||||
|
|
||||||
std::mutex m_realm_mutex;
|
std::mutex m_realm_mutex;
|
||||||
std::vector<std::weak_ptr<Realm>> m_cached_realms;
|
std::vector<CachedRealm> m_cached_realms;
|
||||||
|
|
||||||
std::unique_ptr<_impl::ExternalCommitHelper> m_notifier;
|
std::unique_ptr<_impl::ExternalCommitHelper> m_notifier;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue