Skip to content

Commit ff022d8

Browse files
committed
libexpr: Make positionToDocComment thread-safe
1 parent 75d4ac9 commit ff022d8

2 files changed

Lines changed: 29 additions & 26 deletions

File tree

src/libexpr/eval.cc

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,7 @@ EvalState::EvalState(
303303
, srcToStore(make_ref<decltype(srcToStore)::element_type>())
304304
, importResolutionCache(make_ref<decltype(importResolutionCache)::element_type>())
305305
, fileEvalCache(make_ref<decltype(fileEvalCache)::element_type>())
306+
, positionToDocComment(make_ref<decltype(positionToDocComment)::element_type>())
306307
, regexCache(makeRegexCache())
307308
#if NIX_USE_BOEHMGC
308309
, baseEnvP(std::allocate_shared<Env *>(traceable_allocator<Env *>(), &mem.allocEnv(BASE_ENV_SIZE)))
@@ -3345,19 +3346,21 @@ Expr * EvalState::parse(
33453346
const SourcePath & basePath,
33463347
const std::shared_ptr<StaticEnv> & staticEnv)
33473348
{
3348-
DocCommentMap tmpDocComments; // Only used when not origin is not a SourcePath
3349-
DocCommentMap * docComments = &tmpDocComments;
3349+
auto tmpDocComments = make_ref<DocCommentMap>();
33503350

3351-
if (auto sourcePath = std::get_if<SourcePath>(&origin)) {
3352-
auto [it, _] = positionToDocComment.try_emplace(*sourcePath);
3353-
docComments = &it->second;
3354-
}
3355-
3356-
auto result =
3357-
parseExprFromBuf(text, length, origin, basePath, mem.exprs, symbols, settings, positions, *docComments, rootFS);
3351+
auto result = parseExprFromBuf(
3352+
text, length, origin, basePath, mem.exprs, symbols, settings, positions, *tmpDocComments, rootFS);
33583353

33593354
result->bindVars(*this, staticEnv);
33603355

3356+
if (auto sourcePath = std::get_if<SourcePath>(&origin))
3357+
/* A single file might appear multiple times in PosTable if it's
3358+
parsed by scopedImport. If we are the first then emplace into the map, otherwise
3359+
copy our positions into the existing map. */
3360+
positionToDocComment->emplace_or_visit(*sourcePath, tmpDocComments, [&tmpDocComments](auto & kv) {
3361+
kv.second->insert(tmpDocComments->begin(), tmpDocComments->end());
3362+
});
3363+
33613364
return result;
33623365
}
33633366

@@ -3368,20 +3371,22 @@ ExprAttrs * EvalState::parseReplBindings(
33683371
const SourcePath & basePath,
33693372
const std::shared_ptr<StaticEnv> & staticEnv)
33703373
{
3371-
DocCommentMap tmpDocComments;
3372-
DocCommentMap * docComments = &tmpDocComments;
3373-
3374-
if (auto sourcePath = std::get_if<SourcePath>(&origin)) {
3375-
auto [it, _] = positionToDocComment.try_emplace(*sourcePath);
3376-
docComments = &it->second;
3377-
}
3374+
auto tmpDocComments = make_ref<DocCommentMap>();
33783375

33793376
auto bindings = parseReplBindingsFromBuf(
3380-
text, length, origin, basePath, mem.exprs, symbols, settings, positions, *docComments, rootFS);
3377+
text, length, origin, basePath, mem.exprs, symbols, settings, positions, *tmpDocComments, rootFS);
33813378
assert(bindings);
33823379

33833380
bindings->bindVars(*this, staticEnv);
33843381

3382+
if (auto sourcePath = std::get_if<SourcePath>(&origin))
3383+
/* A single file might appear multiple times in PosTable if it's
3384+
parsed by scopedImport. If we are the first then emplace into the map, otherwise
3385+
copy our positions into the existing map. */
3386+
positionToDocComment->emplace_or_visit(*sourcePath, tmpDocComments, [&tmpDocComments](auto & kv) {
3387+
kv.second->insert(tmpDocComments->begin(), tmpDocComments->end());
3388+
});
3389+
33853390
return bindings;
33863391
}
33873392

@@ -3392,14 +3397,12 @@ DocComment EvalState::getDocCommentForPos(PosIdx pos)
33923397
if (!path)
33933398
return {};
33943399

3395-
auto table = positionToDocComment.find(*path);
3396-
if (table == positionToDocComment.end())
3397-
return {};
3398-
3399-
auto it = table->second.find(pos);
3400-
if (it == table->second.end())
3401-
return {};
3402-
return it->second;
3400+
DocComment result;
3401+
positionToDocComment->visit(*path, [&](const auto & kv) {
3402+
if (auto it = kv.second->find(pos); it != kv.second->end())
3403+
result = it->second;
3404+
});
3405+
return result;
34033406
}
34043407

34053408
std::string ExternalValueBase::coerceToString(

src/libexpr/include/nix/expr/eval.hh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,7 @@ private:
484484
* Associate source positions of certain AST nodes with their preceding doc comment, if they have one.
485485
* Grouped by file.
486486
*/
487-
boost::unordered_flat_map<SourcePath, DocCommentMap> positionToDocComment;
487+
const ref<boost::concurrent_flat_map<SourcePath, ref<DocCommentMap>>> positionToDocComment;
488488

489489
LookupPath lookupPath;
490490

0 commit comments

Comments
 (0)