ilya-biryukov updated this revision to Diff 126957.
ilya-biryukov added a comment.

Merged with head


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D40489

Files:
  clangd/Trace.cpp
  clangd/Trace.h

Index: clangd/Trace.h
===================================================================
--- clangd/Trace.h
+++ clangd/Trace.h
@@ -19,6 +19,7 @@
 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_TRACE_H_
 
 #include "Context.h"
+#include "Function.h"
 #include "JSONExpr.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/Support/raw_ostream.h"
@@ -28,12 +29,24 @@
 namespace trace {
 
 /// A consumer of trace events. The events are produced by Spans and trace::log.
+/// Implmentations of this interface must be thread-safe.
 class EventTracer {
 public:
+  /// A callback executed when an event with duration ends. Args represent data
+  /// that was attached to the event via SPAN_ATTACH.
+  using EndEventCallback = UniqueFunction<void(json::obj &&Args)>;
+
   virtual ~EventTracer() = default;
-  /// Consume a trace event.
-  virtual void event(const Context &Ctx, llvm::StringRef Phase,
-                     json::obj &&Contents) = 0;
+
+  /// Called when event that has a duration starts. The returned callback will
+  /// be executed when the event ends. \p Name is a descriptive name
+  /// of the event that was passed to Span constructor.
+  virtual EndEventCallback beginSpan(const Context &Ctx,
+                                     llvm::StringRef Name) = 0;
+
+  /// Called for instant events.
+  virtual void instant(const Context &Ctx, llvm::StringRef Name,
+                       json::obj &&Args) = 0;
 };
 
 /// Sets up a global EventTracer that consumes events produced by Span and
@@ -50,9 +63,6 @@
 ///
 /// The format is documented here:
 /// https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview
-///
-/// The implementation supports concurrent calls and can be used as a global
-/// tracer (i.e., can be put into a global Context).
 std::unique_ptr<EventTracer> createJSONTracer(llvm::raw_ostream &OS,
                                               bool Pretty = false);
 
@@ -67,16 +77,16 @@
 /// SomeJSONExpr is evaluated and copied only if actually needed.
 class Span {
 public:
-  Span(const Context &Ctx, std::string Name);
+  Span(const Context &Ctx, llvm::StringRef Name);
   ~Span();
 
   /// Returns mutable span metadata if this span is interested.
   /// Prefer to use SPAN_ATTACH rather than accessing this directly.
   json::obj *args() { return Args.get(); }
 
 private:
-  llvm::Optional<Context> Ctx;
   std::unique_ptr<json::obj> Args;
+  EventTracer::EndEventCallback Callback;
 };
 
 #define SPAN_ATTACH(S, Name, Expr)                                             \
Index: clangd/Trace.cpp
===================================================================
--- clangd/Trace.cpp
+++ clangd/Trace.cpp
@@ -44,10 +44,24 @@
     Out.flush();
   }
 
+  EndEventCallback beginSpan(const Context &Ctx,
+                             llvm::StringRef Name) override {
+    jsonEvent("B", json::obj{{"name", Name}});
+
+    // The callback that will run when event ends.
+    return [this](json::Expr &&Args) {
+      jsonEvent("E", json::obj{{"args", std::move(Args)}});
+    };
+  }
+
+  void instant(const Context &Ctx, llvm::StringRef Name,
+               json::obj &&Args) override {
+    jsonEvent("i", json::obj{{"name", Name}, {"args", std::move(Args)}});
+  }
+
   // Record an event on the current thread. ph, pid, tid, ts are set.
   // Contents must be a list of the other JSON key/values.
-  void event(const Context &Ctx, StringRef Phase,
-             json::obj &&Contents) override {
+  void jsonEvent(StringRef Phase, json::obj &&Contents) {
     uint64_t TID = get_threadid();
     std::lock_guard<std::mutex> Lock(Mu);
     // If we haven't already, emit metadata describing this thread.
@@ -109,30 +123,26 @@
 void log(const Context &Ctx, const Twine &Message) {
   if (!T)
     return;
-  T->event(Ctx, "i",
-           json::obj{
-               {"name", "Log"},
-               {"args", json::obj{{"Message", Message.str()}}},
-           });
+  T->instant(Ctx, "Log", json::obj{{"Message", Message.str()}});
 }
 
-Span::Span(const Context &Ctx, std::string Name) {
+Span::Span(const Context &Ctx, llvm::StringRef Name) {
   if (!T)
     return;
-  // Clone the context, so that the original Context can be moved.
-  this->Ctx.emplace(Ctx.clone());
 
-  T->event(*this->Ctx, "B", json::obj{{"name", std::move(Name)}});
+  Callback = T->beginSpan(Ctx, Name);
+  if (!Callback)
+    return;
+
   Args = llvm::make_unique<json::obj>();
 }
 
 Span::~Span() {
-  if (!T)
+  if (!Callback)
     return;
-  if (!Args)
-    Args = llvm::make_unique<json::obj>();
-  T->event(*Ctx, "E",
-           Args ? json::obj{{"args", std::move(*Args)}} : json::obj{});
+
+  assert(Args && "Args must be non-null if Callback is defined");
+  Callback(std::move(*Args));
 }
 
 } // namespace trace
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to