hokein added inline comments.
================
Comment at: clangd/TUScheduler.cpp:268
+ /// Status of the TU.
+ TUStatus Status; /* GUARDED_BY(DiagMu) */
};
----------------
ilya-biryukov wrote:
> hokein wrote:
> > ilya-biryukov wrote:
> > > Is `Status` actually ever read from multiple threads?
> > > I assume it's only accessed on the worker thread, right? I think we can
> > > leave out the locks around it and put beside other fields only accessed
> > > by the worker thread, i.e. `DiagsWereReported`, etc.
> > >
> > > PS Sorry go going back and forth, I didn't think about it in the previous
> > > review iteration.
> > Unfortunately not, most statuses are emitted via worker thread, but we emit
> > `Queued` status in the main thread...
> Hm, that sounds surprising.
> What if the rebuild is in progress on the worker thread and we emit the
> queued status on the main thread at the same time? We might get weird
> sequences of statuses, right?
> E.g. `Queued → BuildingPreamble → [new update on the main thread] Queued →
> [processing request on a worker thread] RunningAction('XRefs')`
>
> The `Queued` request status between `BuildingPreamble` and `RunningAction`
> looks **really** weird.
> Maybe we could avoid that by setting emitting the `Queued` status on the
> worker thread whenever we're about to sleep on the debounce timeout?
This sounds fair enough, and can simplify the code.
> Maybe we could avoid that by setting emitting the Queued status on the worker
> thread whenever we're about to sleep on the debounce timeout?
The `Queued` state is originally designed for the state that the worker thread
is blocked by the max-concurrent-threads semaphore.
Emitting it when we're about to sleep on the debounce timeout doesn't seem a
right place to me. I think a reasonable place is before requiring the `Barrier`.
================
Comment at: clangd/TUScheduler.cpp:636
+ if (Requests.empty())
+ emitTUStatus({TUAction::Idle, /*Name*/ ""});
}
----------------
ilya-biryukov wrote:
> hokein wrote:
> > ilya-biryukov wrote:
> > > Maybe do it outside the lock? The less dependencies between the locks we
> > > have, the better and this one seems unnecessary.
> > Is it safe to read the `Requests` out of the lock here?
> No, but we could store the value of `.empty()` in a local var under the lock.
> The code looks a bit weirder, but that's a small price to pay for less locks
> being held at the same time.
SG.
================
Comment at: clangd/TUScheduler.h:60
+ BuildingPreamble, // The preamble of the TU is being built.
+ BuildingFile, // The TU is being built.
+ Idle, // Indicates the worker thread is idle, and ready to run any upcoming
----------------
ilya-biryukov wrote:
> hokein wrote:
> > ilya-biryukov wrote:
> > > hokein wrote:
> > > > ilya-biryukov wrote:
> > > > > What's the fundamental difference between `BuildingFile` and
> > > > > `RunningAction`?
> > > > > We will often rebuild ASTs while running various actions that read
> > > > > the preamble.
> > > > >
> > > > > Maybe we could squash those two together? One can view diagnostics as
> > > > > an action on the AST, similar to a direct LSP request like
> > > > > findReferences.
> > > > They are two different states, you can think `RunningAction` means the
> > > > AST worker starts processing a task (for example `Update`,
> > > > `GoToDefinition`) and `BuildingFile` means building the AST (which is
> > > > one possible step when processing the task).
> > > >
> > > > In the current implementation, `BuildingPreamble` and `BuildingFile`
> > > > are only emitted when AST worker processes the `Update` task (as we are
> > > > mostly interested in TU states of `ASTWorker::update`); for other AST
> > > > tasks, we just emit `RunningAction` which should be enough.
> > > >
> > > > Given the following requests in the worker queue:
> > > > `[Update]`
> > > > `[GoToDef]`
> > > > `[Update]`
> > > > `[CodeComplete]`
> > > >
> > > > statuses we emitted are
> > > >
> > > > `RunningAction(Update) BuildingPreamble BuildingFile`
> > > > `RunningAction(GoToDef)`
> > > > `RunningAction(Update) BuildingPreamble BuildingFile`
> > > > `RunningAction(GetCurrentPreamble)`
> > > > `Idle`
> > > >
> > > That's the confusing part: clangd might be building the ASTs inside
> > > `RunningAction` too, but we only choose to report `BuildingFile` during
> > > updates.
> > > I would get rid of `BuildingFile` and change it to
> > > `RunningAction(Diagnostics)` instead, it feels like that would allow
> > > avoiding some confusion in the future.
> > >
> > `BuildingFile` might be more natural (understandable) than `Diagnostics`.
> > Two possible ways here:
> >
> > - we can also report `BuildingFile` for other AST tasks, does it reduce the
> > confusing part?
> > - or if you think `Diagnostic` is an important state of `Update`, how about
> > adding a new state `RunningDiagnostic`? `RunningAction` is a higher level
> > information IMO, clangd is running diagnostic inside
> > `RunningAction(Update).`
> >
> > WDYT?
> If you look at the `TUScheduler` as a black box, diagnostics are not that
> much different from other actions reading the AST.
> I'd err on the side of not sending updates unless something interesting is
> actually going on.
> What we're currently doing makes sense (sending a single update per action),
> I think it doesn't really matter if we call it `BuildingFile` or
> `RunningAction("Diagnostics")` or `RunningDiagnostics`. Pick the one you like.
>
> Let's put a comment on `BuildingFile` that it's only emitted when building
> the AST for diagnostics and the read actions emit `RunningAction` instead
>
Done. added comment.
================
Comment at: clangd/TUScheduler.h:57
+ enum State {
+ Unknown,
+ Queued, // The TU is pending in the thread task queue to be
built.
----------------
ilya-biryukov wrote:
> hokein wrote:
> > ilya-biryukov wrote:
> > > Maybe remove this value and leave out the default constructor too?
> > > That would ensure we never fill have `State` field with undefined value
> > > without having this enumerator.
> > > And FWIW, putting **any** value as the default seems fine even if we want
> > > to keep the default ctor, all the users have to set the State anyway.
> > We need the default constructor... When ASTWorker is constructed, we don't
> > know the any state, I'm nervous about putting **any value** as default
> > value (it will hurt the code readability, future readers might be confused
> > -- why the status is `Queued` when constructing).
> >
> > Adding an `Unknown` seems ok to me, it is a common practice...
> `Idle` would be the valid state for an `ASTWorker` with an empty queue. Why
> not use it instead?
>
> Can't disagree using `Unknown` is a common practice, but is it a good one? It
> forces every caller to handle this value, even though it's semantics are
> always unclear.
> Why not use `Optional<EnumWithoutUnkown>` if I really want to indicate the
> lack of value in those cases? Otherwise every `enum` type implements its own
> version of `Optional`.
`Idle` seems a compromising state for initialization.
Repository:
rCTE Clang Tools Extra
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D54796/new/
https://reviews.llvm.org/D54796
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits