ilya-biryukov added inline comments.

================
Comment at: clangd/Context.h:11
+// Context for storing and retrieving implicit data. Useful for passing 
implicit
+// parameters on a per-request basis.
+//
----------------
sammccall wrote:
> This could use a bit more I think, e.g.
> 
>     A context is an immutable container for per-request data that must be 
> propagated through layers that don't care about it.
>     An example is a request ID that we may want to use when logging.
> 
>     Conceptually, a context is a heterogeneous map<Key<T>, T>. Each key has 
>     an associated value type, which allows the map to be typesafe.
> 
>     You can't add data to an existing context, instead you create a new 
> immutable context derived from it with extra data added. When you retrieve 
> data, the context will walk up the parent chain until the key is found.
> 
>     Contexts should be:
>      - passed by reference when calling synchronous functions
>      - passed by value (move) when calling asynchronous functions. The 
> callback will receive the context again.
>      - copied only when 'forking' an asynchronous computation that we don't 
> wait for
> 
> Some of this is on the class comment - this seems fine but the Context class 
> should then be the first thing in the file.
Done. It's in the class comment, but class is now the first thing in the file.
Thanks for making my life a bit easier and coming up with a doc :-)


================
Comment at: clangd/Context.h:25
+
+class ContextData {
+public:
----------------
ilya-biryukov wrote:
> sammccall wrote:
> > IIUC, the only reason we expose separate `Context` and `ContextData` types 
> > is to give things like Span a stable reference to hold onto 
> > (`ContextData*`).
> > 
> > Could we use `Context` instead (a copy)? Then we incur `shared_ptr` 
> > overhead for span creation, but greatly simplify the interface.
> > If we want to avoid the overhead, the Span could maybe grab whatever it 
> > needs out of the context at construction time, for use in the destructor.
> > 
> > Either way, we should make sure `Context` is front-and-center in this 
> > header, and I hope we can hide ContextData entirely.
> I have considered making `Context` the only used interface, but I hated the 
> fact that each `Span` constructor would copy a `shared_ptr`.  (And `Span`s 
> can be pretty ubiquitous).
> On the other hand, that should not happen when tracing is off, so we won't be 
> adding overhead when `Span` are not used.
> Will try moving `ContextData` into `.cpp` file, this should certainly be an 
> implementation detail. And we can expose it later if we'll actually have a 
> use-case for that (i.e. not copying `shared_ptr`s).
Done. We now store a copied Context in the Spans.


================
Comment at: clangd/Context.h:32
+  /// specified for \p Key, return null.
+  template <class Type> Type *get(Key<Type> &Key) const {
+    if (auto Val = Data.get(Key))
----------------
sammccall wrote:
> sammccall wrote:
> > nit: const Key&, and below
> this isn't usually how we define const-correctness for containers.
> A const method shouldn't return a mutable reference to the contained object.
Returning const references now.


================
Comment at: clangd/Context.h:42
+  /// Must not be called for keys that are not in the map.
+  template <class Type> Type &getExisting(Key<Type> &Key) const {
+    auto Val = get(Key);
----------------
sammccall wrote:
> I'd prefer the standard name `at` for this function (assert vs throw being 
> pretty minor I think), but YMMV
We've discussed this offline, but just for the record:
I kinda like that `getExisting` is named after `get`. Also `at` usually throws, 
whereas our function only `asserts` (even though LLVM does not use execptions, 
we still have undefined behaviour vs crash in runtime).



================
Comment at: clangd/Context.h:139
+/// that require a Context when no explicit Context is not available.
+Context &emptyCtx();
+
----------------
sammccall wrote:
> sammccall wrote:
> > nit: how do you feel about Context::empty()? it ties the name to the type 
> > more clearly, I think.
> OOC: why reference and not a value?
> nit: how do you feel about Context::empty()? it ties the name to the type 
> more clearly, I think.
Done.

> OOC: why reference and not a value?
Reference gives us just the right semantics with less overhead (no extra 
shared_ptr copies) when we need to pass empty context by reference (e.g., to 
sync functions like `log`).


================
Comment at: clangd/Context.h:142
+/// Creates a ContextBuilder with a null parent.
+ContextBuilder buildCtx();
+
----------------
sammccall wrote:
> I think we should spell this `emptyCtx().derive()`.
> It should be pretty rare to derive from the empty context in production code 
> - and conceptually it's no different than any other use of the empty context, 
> I think.
I'd argue the separate function is more readable and saves us an extra lookup 
in the empty context for missing keys.
Given that `emptyCtx` is now `Context::empty`, maybe we should also change 
`buildCtx`  to `Context::build`?


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D40485



_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to