We need recursive locks to synchronize access.

We can certainly revert to simple locks, but then have to do synchronization differently than the Java target does, which is not in the scope of the current work.
This commit is contained in:
Mike Lischke 2016-04-30 13:14:57 +02:00
parent 8cd043a6de
commit 99ada0550f
13 changed files with 19 additions and 18 deletions

View File

@ -238,7 +238,7 @@ const atn::ATN& Parser::getATNWithBypassAlts() {
throw UnsupportedOperationException("The current parser does not support an ATN with bypass alternatives."); throw UnsupportedOperationException("The current parser does not support an ATN with bypass alternatives.");
} }
std::lock_guard<std::mutex> lck(mtx); std::lock_guard<std::recursive_mutex> lck(mtx);
// XXX: using the entire serialized ATN as key into the map is a big resource waste. // XXX: using the entire serialized ATN as key into the map is a big resource waste.
// How large can that thing become? // How large can that thing become?
@ -572,7 +572,7 @@ std::vector<std::wstring> Parser::getRuleInvocationStack(Ref<RuleContext> p) {
std::vector<std::wstring> Parser::getDFAStrings() { std::vector<std::wstring> Parser::getDFAStrings() {
atn::ParserATNSimulator *simulator = getInterpreter<atn::ParserATNSimulator>(); atn::ParserATNSimulator *simulator = getInterpreter<atn::ParserATNSimulator>();
if (!simulator->decisionToDFA.empty()) { if (!simulator->decisionToDFA.empty()) {
std::lock_guard<std::mutex> lck(mtx); std::lock_guard<std::recursive_mutex> lck(mtx);
std::vector<std::wstring> s; std::vector<std::wstring> s;
for (size_t d = 0; d < simulator->decisionToDFA.size(); d++) { for (size_t d = 0; d < simulator->decisionToDFA.size(); d++) {
@ -587,7 +587,7 @@ std::vector<std::wstring> Parser::getDFAStrings() {
void Parser::dumpDFA() { void Parser::dumpDFA() {
atn::ParserATNSimulator *simulator = getInterpreter<atn::ParserATNSimulator>(); atn::ParserATNSimulator *simulator = getInterpreter<atn::ParserATNSimulator>();
if (!simulator->decisionToDFA.empty()) { if (!simulator->decisionToDFA.empty()) {
std::lock_guard<std::mutex> lck(mtx); std::lock_guard<std::recursive_mutex> lck(mtx);
bool seenOne = false; bool seenOne = false;
for (size_t d = 0; d < simulator->decisionToDFA.size(); d++) { for (size_t d = 0; d < simulator->decisionToDFA.size(); d++) {
dfa::DFA &dfa = simulator->decisionToDFA[d]; dfa::DFA &dfa = simulator->decisionToDFA[d];

View File

@ -425,7 +425,7 @@ namespace runtime {
std::vector<int> _precedenceStack; std::vector<int> _precedenceStack;
//Mutex to manage synchronized access for multithreading in the parser //Mutex to manage synchronized access for multithreading in the parser
std::mutex mtx; std::recursive_mutex mtx;
/// <summary> /// <summary>
/// Specifies whether or not the parser should construct a parse tree during /// Specifies whether or not the parser should construct a parse tree during

View File

@ -60,7 +60,7 @@ Ref<dfa::Vocabulary> Recognizer::getVocabulary() const {
std::map<std::wstring, size_t> Recognizer::getTokenTypeMap() { std::map<std::wstring, size_t> Recognizer::getTokenTypeMap() {
Ref<dfa::Vocabulary> vocabulary = getVocabulary(); Ref<dfa::Vocabulary> vocabulary = getVocabulary();
std::lock_guard<std::mutex> lck(mtx); std::lock_guard<std::recursive_mutex> lck(mtx);
std::map<std::wstring, size_t> result; std::map<std::wstring, size_t> result;
auto iterator = _tokenTypeMapCache.find(vocabulary); auto iterator = _tokenTypeMapCache.find(vocabulary);
if (iterator != _tokenTypeMapCache.end()) { if (iterator != _tokenTypeMapCache.end()) {
@ -90,7 +90,7 @@ std::map<std::wstring, size_t> Recognizer::getRuleIndexMap() {
throw L"The current recognizer does not provide a list of rule names."; throw L"The current recognizer does not provide a list of rule names.";
} }
std::lock_guard<std::mutex> lck(mtx); std::lock_guard<std::recursive_mutex> lck(mtx);
std::map<std::wstring, size_t> result; std::map<std::wstring, size_t> result;
auto iterator = _ruleIndexMapCache.find(ruleNames); auto iterator = _ruleIndexMapCache.find(ruleNames);
if (iterator != _ruleIndexMapCache.end()) { if (iterator != _ruleIndexMapCache.end()) {

View File

@ -181,7 +181,7 @@ namespace runtime {
ProxyErrorListener _proxListener; // Manages a collection of listeners. ProxyErrorListener _proxListener; // Manages a collection of listeners.
// Mutex to manage synchronized access for multithreading. // Mutex to manage synchronized access for multithreading.
std::mutex mtx; std::recursive_mutex mtx;
int _stateNumber; int _stateNumber;

View File

@ -56,7 +56,7 @@ Ref<PredictionContextCache> ATNSimulator::getSharedContextCache() {
} }
Ref<PredictionContext> ATNSimulator::getCachedContext(Ref<PredictionContext> context) { Ref<PredictionContext> ATNSimulator::getCachedContext(Ref<PredictionContext> context) {
std::lock_guard<std::mutex> lck(mtx); std::lock_guard<std::recursive_mutex> lck(mtx);
std::map<Ref<PredictionContext>, Ref<PredictionContext>> visited; std::map<Ref<PredictionContext>, Ref<PredictionContext>> visited;
return PredictionContext::getCachedContext(context, _sharedContextCache, visited); return PredictionContext::getCachedContext(context, _sharedContextCache, visited);
} }

View File

@ -85,7 +85,7 @@ namespace atn {
protected: protected:
// Mutex to manage synchronized access for multithreading // Mutex to manage synchronized access for multithreading
std::mutex mtx; std::recursive_mutex mtx;
/// <summary> /// <summary>
/// The context cache maps all PredictionContext objects that are equals() /// The context cache maps all PredictionContext objects that are equals()

View File

@ -563,7 +563,7 @@ void LexerATNSimulator::addDFAEdge(dfa::DFAState *p, ssize_t t, dfa::DFAState *q
std::wcout << std::wstring(L"EDGE ") << p << std::wstring(L" -> ") << q << std::wstring(L" upon ") << (static_cast<wchar_t>(t)) << std::endl; std::wcout << std::wstring(L"EDGE ") << p << std::wstring(L" -> ") << q << std::wstring(L" upon ") << (static_cast<wchar_t>(t)) << std::endl;
} }
std::lock_guard<std::mutex> lck(mtx); std::lock_guard<std::recursive_mutex> lck(mtx);
if (p->edges.empty()) { if (p->edges.empty()) {
// make room for tokens 1..n and -1 masquerading as index 0 // make room for tokens 1..n and -1 masquerading as index 0
p->edges.resize(MAX_DFA_EDGE - MIN_DFA_EDGE + 1); p->edges.resize(MAX_DFA_EDGE - MIN_DFA_EDGE + 1);
@ -595,7 +595,7 @@ dfa::DFAState *LexerATNSimulator::addDFAState(Ref<ATNConfigSet> configs) {
dfa::DFA &dfa = _decisionToDFA[_mode]; dfa::DFA &dfa = _decisionToDFA[_mode];
{ {
std::lock_guard<std::mutex> lck(mtx); std::lock_guard<std::recursive_mutex> lck(mtx);
auto iterator = dfa.states.find(proposed); auto iterator = dfa.states.find(proposed);
if (iterator != dfa.states.end()) { if (iterator != dfa.states.end()) {

View File

@ -1205,7 +1205,7 @@ dfa::DFAState *ParserATNSimulator::addDFAEdge(dfa::DFA &dfa, dfa::DFAState *from
} }
{ {
std::lock_guard<std::mutex> lck(mtx); std::lock_guard<std::recursive_mutex> lck(mtx);
if (from->edges.empty()) if (from->edges.empty())
from->edges.resize(atn.maxTokenType + 1 + 1); from->edges.resize(atn.maxTokenType + 1 + 1);
from->edges[(size_t)(t + 1)] = to; // connect from->edges[(size_t)(t + 1)] = to; // connect
@ -1228,7 +1228,7 @@ dfa::DFAState *ParserATNSimulator::addDFAState(dfa::DFA &dfa, dfa::DFAState *D)
} }
{ {
std::lock_guard<std::mutex> lck(mtx); std::lock_guard<std::recursive_mutex> lck(mtx);
auto existing = dfa.states.find(D); auto existing = dfa.states.find(D);
if (existing != dfa.states.end()) { if (existing != dfa.states.end()) {

View File

@ -290,7 +290,7 @@ namespace atn {
PredictionMode mode; PredictionMode mode;
// Mutex to manage synchronized access for multithreading in the parser atn simulator. // Mutex to manage synchronized access for multithreading in the parser atn simulator.
std::mutex _lock; std::recursive_mutex _lock;
/// <summary> /// <summary>
/// Each prediction operation uses a cache for merge of prediction contexts. /// Each prediction operation uses a cache for merge of prediction contexts.

View File

@ -106,7 +106,7 @@ void DFA::setPrecedenceStartState(int precedence, DFAState *startState) {
// synchronization on s0 here is ok. when the DFA is turned into a // synchronization on s0 here is ok. when the DFA is turned into a
// precedence DFA, s0 will be initialized once and not updated again // precedence DFA, s0 will be initialized once and not updated again
std::unique_lock<std::mutex> lock(_lock); std::unique_lock<std::recursive_mutex> lock(_lock);
{ {
// s0.edges is never null for a precedence DFA // s0.edges is never null for a precedence DFA
if (precedence >= (int)s0->edges.size()) { if (precedence >= (int)s0->edges.size()) {

View File

@ -109,7 +109,7 @@ namespace dfa {
*/ */
bool _precedenceDfa; bool _precedenceDfa;
std::mutex _lock; // To synchronize access to s0. std::recursive_mutex _lock; // To synchronize access to s0.
}; };
} // namespace atn } // namespace atn

View File

@ -29,11 +29,13 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "VocabularyImpl.h"
#include "LexerDFASerializer.h" #include "LexerDFASerializer.h"
using namespace org::antlr::v4::runtime::dfa; using namespace org::antlr::v4::runtime::dfa;
LexerDFASerializer::LexerDFASerializer(DFA *dfa) : DFASerializer(dfa, lexerTokenNames_) { LexerDFASerializer::LexerDFASerializer(DFA *dfa) : DFASerializer(dfa, VocabularyImpl::EMPTY_VOCABULARY) {
} }
std::wstring LexerDFASerializer::getEdgeLabel(size_t i) const { std::wstring LexerDFASerializer::getEdgeLabel(size_t i) const {

View File

@ -44,7 +44,6 @@ namespace dfa {
LexerDFASerializer(DFA *dfa); LexerDFASerializer(DFA *dfa);
protected: protected:
std::vector<std::wstring> lexerTokenNames_;
virtual std::wstring getEdgeLabel(size_t i) const override; virtual std::wstring getEdgeLabel(size_t i) const override;
}; };