Use a `recursive_mutex` instead of a `mutex`.

This allow us to internally call thread_safe function from already
locked context.
This commit is contained in:
Matthieu Gautier 2024-01-19 11:06:17 +01:00
parent c768d05b5b
commit 9b9c61a194
2 changed files with 18 additions and 18 deletions

View File

@ -408,7 +408,7 @@ private: // functions
void dropCache(const std::string& bookId); void dropCache(const std::string& bookId);
private: //data private: //data
mutable std::mutex m_mutex; mutable std::recursive_mutex m_mutex;
Library::Revision m_revision; Library::Revision m_revision;
std::map<std::string, Entry> m_books; std::map<std::string, Entry> m_books;
using ArchiveCache = ConcurrentCache<std::string, std::shared_ptr<zim::Archive>>; using ArchiveCache = ConcurrentCache<std::string, std::shared_ptr<zim::Archive>>;

View File

@ -110,7 +110,7 @@ Library::~Library() = default;
bool Library::addBook(const Book& book) bool Library::addBook(const Book& book)
{ {
std::lock_guard<std::mutex> lock(m_mutex); std::lock_guard<std::recursive_mutex> lock(m_mutex);
++m_revision; ++m_revision;
/* Try to find it */ /* Try to find it */
updateBookDB(book); updateBookDB(book);
@ -141,13 +141,13 @@ bool Library::addBook(const Book& book)
void Library::addBookmark(const Bookmark& bookmark) void Library::addBookmark(const Bookmark& bookmark)
{ {
std::lock_guard<std::mutex> lock(m_mutex); std::lock_guard<std::recursive_mutex> lock(m_mutex);
m_bookmarks.push_back(bookmark); m_bookmarks.push_back(bookmark);
} }
bool Library::removeBookmark(const std::string& zimId, const std::string& url) bool Library::removeBookmark(const std::string& zimId, const std::string& url)
{ {
std::lock_guard<std::mutex> lock(m_mutex); std::lock_guard<std::recursive_mutex> lock(m_mutex);
for(auto it=m_bookmarks.begin(); it!=m_bookmarks.end(); it++) { for(auto it=m_bookmarks.begin(); it!=m_bookmarks.end(); it++) {
if (it->getBookId() == zimId && it->getUrl() == url) { if (it->getBookId() == zimId && it->getUrl() == url) {
m_bookmarks.erase(it); m_bookmarks.erase(it);
@ -166,7 +166,7 @@ void Library::dropCache(const std::string& id)
bool Library::removeBookById(const std::string& id) bool Library::removeBookById(const std::string& id)
{ {
std::lock_guard<std::mutex> lock(m_mutex); std::lock_guard<std::recursive_mutex> lock(m_mutex);
m_bookDB->delete_document("Q" + id); m_bookDB->delete_document("Q" + id);
dropCache(id); dropCache(id);
// We do not change the cache size here // We do not change the cache size here
@ -184,7 +184,7 @@ bool Library::removeBookById(const std::string& id)
Library::Revision Library::getRevision() const Library::Revision Library::getRevision() const
{ {
std::lock_guard<std::mutex> lock(m_mutex); std::lock_guard<std::recursive_mutex> lock(m_mutex);
return m_revision; return m_revision;
} }
@ -192,7 +192,7 @@ uint32_t Library::removeBooksNotUpdatedSince(Revision libraryRevision)
{ {
BookIdCollection booksToRemove; BookIdCollection booksToRemove;
{ {
std::lock_guard<std::mutex> lock(m_mutex); std::lock_guard<std::recursive_mutex> lock(m_mutex);
for ( const auto& entry : m_books) { for ( const auto& entry : m_books) {
if ( entry.second.lastUpdatedRevision <= libraryRevision ) { if ( entry.second.lastUpdatedRevision <= libraryRevision ) {
booksToRemove.push_back(entry.first); booksToRemove.push_back(entry.first);
@ -217,7 +217,7 @@ const Book& Library::getBookById(const std::string& id) const
Book Library::getBookByIdThreadSafe(const std::string& id) const Book Library::getBookByIdThreadSafe(const std::string& id) const
{ {
std::lock_guard<std::mutex> lock(m_mutex); std::lock_guard<std::recursive_mutex> lock(m_mutex);
return getBookById(id); return getBookById(id);
} }
@ -275,7 +275,7 @@ std::shared_ptr<ZimSearcher> Library::getSearcherByIds(const BookIdSet& ids)
unsigned int Library::getBookCount(const bool localBooks, unsigned int Library::getBookCount(const bool localBooks,
const bool remoteBooks) const const bool remoteBooks) const
{ {
std::lock_guard<std::mutex> lock(m_mutex); std::lock_guard<std::recursive_mutex> lock(m_mutex);
return getBookCount_not_protected(localBooks, remoteBooks); return getBookCount_not_protected(localBooks, remoteBooks);
} }
@ -288,7 +288,7 @@ bool Library::writeToFile(const std::string& path) const
dumper.setBaseDir(baseDir); dumper.setBaseDir(baseDir);
std::string xml; std::string xml;
{ {
std::lock_guard<std::mutex> lock(m_mutex); std::lock_guard<std::recursive_mutex> lock(m_mutex);
xml = dumper.dumpLibXMLContent(allBookIds); xml = dumper.dumpLibXMLContent(allBookIds);
}; };
return writeTextFile(path, xml); return writeTextFile(path, xml);
@ -304,7 +304,7 @@ bool Library::writeBookmarksToFile(const std::string& path) const
Library::AttributeCounts Library::getBookAttributeCounts(BookStrPropMemFn p) const Library::AttributeCounts Library::getBookAttributeCounts(BookStrPropMemFn p) const
{ {
std::lock_guard<std::mutex> lock(m_mutex); std::lock_guard<std::recursive_mutex> lock(m_mutex);
AttributeCounts propValueCounts; AttributeCounts propValueCounts;
for (const auto& pair: m_books) { for (const auto& pair: m_books) {
@ -336,7 +336,7 @@ std::vector<std::string> Library::getBooksLanguages() const
Library::AttributeCounts Library::getBooksLanguagesWithCounts() const Library::AttributeCounts Library::getBooksLanguagesWithCounts() const
{ {
std::lock_guard<std::mutex> lock(m_mutex); std::lock_guard<std::recursive_mutex> lock(m_mutex);
AttributeCounts langsWithCounts; AttributeCounts langsWithCounts;
for (const auto& pair: m_books) { for (const auto& pair: m_books) {
@ -352,7 +352,7 @@ Library::AttributeCounts Library::getBooksLanguagesWithCounts() const
std::vector<std::string> Library::getBooksCategories() const std::vector<std::string> Library::getBooksCategories() const
{ {
std::lock_guard<std::mutex> lock(m_mutex); std::lock_guard<std::recursive_mutex> lock(m_mutex);
std::set<std::string> categories; std::set<std::string> categories;
for (const auto& pair: m_books) { for (const auto& pair: m_books) {
@ -383,7 +383,7 @@ const std::vector<kiwix::Bookmark> Library::getBookmarks(bool onlyValidBookmarks
} }
std::vector<kiwix::Bookmark> validBookmarks; std::vector<kiwix::Bookmark> validBookmarks;
auto booksId = getBooksIds(); auto booksId = getBooksIds();
std::lock_guard<std::mutex> lock(m_mutex); std::lock_guard<std::recursive_mutex> lock(m_mutex);
for(auto& bookmark:m_bookmarks) { for(auto& bookmark:m_bookmarks) {
if (std::find(booksId.begin(), booksId.end(), bookmark.getBookId()) != booksId.end()) { if (std::find(booksId.begin(), booksId.end(), bookmark.getBookId()) != booksId.end()) {
validBookmarks.push_back(bookmark); validBookmarks.push_back(bookmark);
@ -394,7 +394,7 @@ const std::vector<kiwix::Bookmark> Library::getBookmarks(bool onlyValidBookmarks
Library::BookIdCollection Library::getBooksIds() const Library::BookIdCollection Library::getBooksIds() const
{ {
std::lock_guard<std::mutex> lock(m_mutex); std::lock_guard<std::recursive_mutex> lock(m_mutex);
BookIdCollection bookIds; BookIdCollection bookIds;
for (auto& pair: m_books) { for (auto& pair: m_books) {
@ -600,7 +600,7 @@ Library::BookIdCollection Library::filterViaBookDB(const Filter& filter) const
BookIdCollection bookIds; BookIdCollection bookIds;
std::lock_guard<std::mutex> lock(m_mutex); std::lock_guard<std::recursive_mutex> lock(m_mutex);
Xapian::Enquire enquire(*m_bookDB); Xapian::Enquire enquire(*m_bookDB);
enquire.set_query(query); enquire.set_query(query);
const auto results = enquire.get_mset(0, m_books.size()); const auto results = enquire.get_mset(0, m_books.size());
@ -615,7 +615,7 @@ Library::BookIdCollection Library::filter(const Filter& filter) const
{ {
BookIdCollection result; BookIdCollection result;
const auto preliminaryResult = filterViaBookDB(filter); const auto preliminaryResult = filterViaBookDB(filter);
std::lock_guard<std::mutex> lock(m_mutex); std::lock_guard<std::recursive_mutex> lock(m_mutex);
for(auto id : preliminaryResult) { for(auto id : preliminaryResult) {
if(filter.accept(m_books.at(id))) { if(filter.accept(m_books.at(id))) {
result.push_back(id); result.push_back(id);
@ -689,7 +689,7 @@ void Library::sort(BookIdCollection& bookIds, supportedListSortBy sort, bool asc
// NOTE: for the entire duration of the sort. Will need to obtain (under a // NOTE: for the entire duration of the sort. Will need to obtain (under a
// NOTE: lock) the required atributes from the books once, and then the // NOTE: lock) the required atributes from the books once, and then the
// NOTE: sorting will run on a copy of data without locking. // NOTE: sorting will run on a copy of data without locking.
std::lock_guard<std::mutex> lock(m_mutex); std::lock_guard<std::recursive_mutex> lock(m_mutex);
switch(sort) { switch(sort) {
case TITLE: case TITLE:
std::sort(bookIds.begin(), bookIds.end(), Comparator<TITLE>(this, ascending)); std::sort(bookIds.begin(), bookIds.end(), Comparator<TITLE>(this, ascending));