[Automaton] Make Automaton thread-safe
authorJames Molloy <James Molloy jmolloy@google.com>
Tue, 5 Nov 2019 22:53:56 +0000 (22:53 +0000)
committerJames Molloy <James Molloy jmolloy@google.com>
Tue, 5 Nov 2019 22:57:44 +0000 (22:57 +0000)
In an optimization to improve performance (rL375240) we added a std::shared_ptr
around the main table map. This is safe, but we also ended up making the
transcriber object a std::shared_ptr too. This has mutable state, so must be
copied when we copy the Automaton object. This is very cheap; the main optimization
was about the map `M` only.

Reported by Dan Palermo. No test as triggering this is rather hard from a unit test.

llvm/include/llvm/Support/Automaton.h

index 7c13a69..c2b9213 100644 (file)
@@ -117,6 +117,10 @@ public:
     reset();
   }
 
+  ArrayRef<NfaStatePair> getTransitionInfo() const {
+    return TransitionInfo;
+  }
+
   void reset() {
     Paths.clear();
     Heads.clear();
@@ -198,7 +202,13 @@ public:
       M->emplace(std::make_pair(I.FromDfaState, I.Action),
                  std::make_pair(I.ToDfaState, I.InfoIdx));
   }
-  Automaton(const Automaton &) = default;
+  Automaton(const Automaton &Other)
+      : M(Other.M), State(Other.State), Transcribe(Other.Transcribe) {
+    // Transcriber is not thread-safe, so create a new instance on copy.
+    if (Other.Transcriber)
+      Transcriber = std::make_shared<internal::NfaTranscriber>(
+          Other.Transcriber->getTransitionInfo());
+  }
 
   /// Reset the automaton to its initial state.
   void reset() {