ATN: Remove race condition in addState(ATNState*)

This is a proposed fix to bug #1826 which removes a race condition where
multiple threads could update ATNState::nextTokenWithinRule, leading to
corrupted std::vector instances in an InstanceSet.
This commit is contained in:
Jan Martin Mikkelsen 2017-06-11 11:23:33 +10:00
parent 4a359c1831
commit 70402f8eff
3 changed files with 9 additions and 5 deletions

View File

@ -88,10 +88,10 @@ misc::IntervalSet ATN::nextTokens(ATNState *s, RuleContext *ctx) const {
}
misc::IntervalSet& ATN::nextTokens(ATNState *s) const {
if (s->nextTokenWithinRule.isEmpty()) {
auto candidate = nextTokens(s, nullptr);
if (!candidate.isEmpty() || !s->nextTokenWithinRule.isReadOnly()) {
s->nextTokenWithinRule = candidate;
if (!s->nextTokenWithinRule.isReadOnly()) {
std::unique_lock<std::mutex> lock { _mutex };
if (!s->nextTokenWithinRule.isReadOnly()) {
s->nextTokenWithinRule = nextTokens(s, nullptr);
s->nextTokenWithinRule.setReadOnly(true);
}
}

View File

@ -103,6 +103,9 @@ namespace atn {
virtual misc::IntervalSet getExpectedTokens(size_t stateNumber, RuleContext *context) const;
std::string toString() const;
private:
mutable std::mutex _mutex;
};
} // namespace atn

View File

@ -6,6 +6,7 @@
#pragma once
#include "misc/Interval.h"
#include <atomic>
namespace antlr4 {
namespace misc {
@ -30,7 +31,7 @@ namespace misc {
protected:
/// The list of sorted, disjoint intervals.
std::vector<Interval> _intervals;
bool _readonly;
std::atomic<bool> _readonly;
public:
IntervalSet();