From 026c049512cfdca600fbf75a69706a5c72ad9a61 Mon Sep 17 00:00:00 2001 From: Chris Frey Date: Thu, 9 Feb 2012 15:46:11 -0500 Subject: [PATCH] desktop: made the thread locks more forgiving when pre-loading When loading a large database from a slow device, the old single lock system blocked unnecessarily. This commit allows for locking of the map and locking of the load, so accessing pre-loaded data is still possible during background device access. --- desktop/src/Mode_Browse.cc | 38 +++++++++++++++++++++++++++++++------- desktop/src/Mode_Browse.h | 1 + 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/desktop/src/Mode_Browse.cc b/desktop/src/Mode_Browse.cc index cd604bf4..8405ad8f 100644 --- a/desktop/src/Mode_Browse.cc +++ b/desktop/src/Mode_Browse.cc @@ -393,21 +393,45 @@ DBMap::DBMap(ThreadableDesktop &tdesktop) if( pthread_mutex_init(&m_map_mutex, NULL) ) { throw Barry::Error("Failed to create map mutex"); } + + if( pthread_mutex_init(&m_load_mutex, NULL) ) { + throw Barry::Error("Failed to create load mutex"); + } } DBMap::DBCachePtr DBMap::LoadDBCache(const std::string &dbname) { - scoped_lock lock(m_map_mutex); + // first, check for pre-loaded data, before the load lock, + // to make sure we return pre-loaded data with utmost haste + { + scoped_lock map_lock(m_map_mutex); - MapType::iterator i = m_map.find(dbname); - if( i != m_map.end() ) - return i->second; + MapType::iterator i = m_map.find(dbname); + if( i != m_map.end() ) + return i->second; + } + + // if not found, lock and load, but be careful, since we + // don't want to open a window here for loading a db twice + scoped_lock load_lock(m_load_mutex); - // do not unlock here, since we only want to load this - // data once, not provide a window for loading it twice + // check again for pre-loaded data, since between + // map.unlock and load.lock there could have been + // another successful load + { + scoped_lock map_lock(m_map_mutex); - // not found, time to load it up + MapType::iterator i = m_map.find(dbname); + if( i != m_map.end() ) + return i->second; + } + + // do the load, without map.lock, since this can take a + // significant amount of time DBCachePtr p( new DBCache(m_tdesktop, dbname) ); + + // lock once more to update the map, and then done + scoped_lock map_lock(m_map_mutex); m_map[dbname] = p; return p; } diff --git a/desktop/src/Mode_Browse.h b/desktop/src/Mode_Browse.h index ced49b88..4569a3db 100644 --- a/desktop/src/Mode_Browse.h +++ b/desktop/src/Mode_Browse.h @@ -311,6 +311,7 @@ private: ThreadableDesktop &m_tdesktop; MapType m_map; pthread_mutex_t m_map_mutex; + pthread_mutex_t m_load_mutex; public: DBMap(ThreadableDesktop &tdesktop); -- 2.11.4.GIT