[poppler] poppler/Dict.cc poppler/Dict.h

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Sep 21 12:29:14 UTC 2018


 poppler/Dict.cc |   24 ++++++++++++++----------
 poppler/Dict.h  |    2 +-
 2 files changed, 15 insertions(+), 11 deletions(-)

New commits:
commit 06c344ccb8ccfafa9c506f40226ea2cce0e5f75c
Author: Adam Reichold <adam.reichold at t-online.de>
Date:   Fri Sep 21 09:43:40 2018 +0200

    Use deferred sorting with Dict again to avoid performance regression
    
    This tries to move sorting a Dict into the first find call again, but tries
    harder to make the double-checked locking work correctly so that at least
    concurrent calls to find are correct (but concurrent calls to find and
    add, set or remove are still not allowed).

diff --git a/poppler/Dict.cc b/poppler/Dict.cc
index 400b5885..0a0ceab3 100644
--- a/poppler/Dict.cc
+++ b/poppler/Dict.cc
@@ -85,7 +85,7 @@ Dict::Dict(const Dict* dictA) {
     entries.emplace_back(entry.first, entry.second.copy());
   }
 
-  sorted = dictA->sorted;
+  sorted = dictA->sorted.load();
 }
 
 Dict *Dict::copy(XRef *xrefA) const {
@@ -108,20 +108,24 @@ Dict::~Dict() {
 
 void Dict::add(const char *key, Object &&val) {
   dictLocker();
+  entries.emplace_back(key, std::move(val));
+  sorted = false;
+}
+
+inline const Dict::DictEntry *Dict::find(const char *key) const {
   if (entries.size() >= SORT_LENGTH_LOWER_LIMIT) {
     if (!sorted) {
-      std::sort(entries.begin(), entries.end(), CmpDictEntry{});
-      sorted = true;
+      dictLocker();
+      if (!sorted) {
+	auto& entries = const_cast<std::vector<DictEntry>&>(this->entries);
+	auto& sorted = const_cast<std::atomic_bool&>(this->sorted);
+
+	std::sort(entries.begin(), entries.end(), CmpDictEntry{});
+	sorted = true;
+      }
     }
-    const auto pos = std::upper_bound(entries.begin(), entries.end(), key, CmpDictEntry{});
-    entries.emplace(pos, key, std::move(val));
-  } else {
-    entries.emplace_back(key, std::move(val));
-    sorted = false;
   }
-}
 
-inline const Dict::DictEntry *Dict::find(const char *key) const {
   if (sorted) {
     const auto pos = std::lower_bound(entries.begin(), entries.end(), key, CmpDictEntry{});
     if (pos != entries.end() && pos->first == key) {
diff --git a/poppler/Dict.h b/poppler/Dict.h
index d7ade695..a4fd1c56 100644
--- a/poppler/Dict.h
+++ b/poppler/Dict.h
@@ -110,7 +110,7 @@ private:
   using DictEntry = std::pair<std::string, Object>;
   struct CmpDictEntry;
 
-  bool sorted;
+  std::atomic_bool sorted;
   XRef *xref;			// the xref table for this PDF file
   std::vector<DictEntry> entries;
   std::atomic_int ref;			// reference count


More information about the poppler mailing list