================
@@ -174,6 +176,82 @@ struct StatisticsOptions {
   std::optional<bool> m_include_transcript;
 };
 
+/// A class that represents statistics about a TypeSummaryProviders invocations
+class SummaryStatistics {
+public:
+  explicit SummaryStatistics(std::string name, std::string impl_type)
+      : m_total_time(), m_impl_type(impl_type), m_name(name), m_count(0) {}
+
+  std::string GetName() const { return m_name; };
+  double GetTotalTime() const { return m_total_time.get().count(); }
+
+  uint64_t GetSummaryCount() const {
+    return m_count.load(std::memory_order_relaxed);
+  }
+
+  StatsDuration &GetDurationReference() { return m_total_time; };
+
+  std::string GetSummaryKindName() const { return m_impl_type; }
+
+  llvm::json::Value ToJSON() const;
+
+  /// Basic RAII class to increment the summary count when the call is 
complete.
+  class SummaryInvocation {
+  public:
+    SummaryInvocation(std::shared_ptr<SummaryStatistics> summary_stats)
+        : m_stats(summary_stats),
+          m_elapsed_time(summary_stats->GetDurationReference()) {}
+    ~SummaryInvocation() { m_stats->OnInvoked(); }
+
+    /// Delete the copy constructor and assignment operator to prevent
+    /// accidental double counting.
+    /// @{
+    SummaryInvocation(const SummaryInvocation &) = delete;
+    SummaryInvocation &operator=(const SummaryInvocation &) = delete;
+    /// @}
+
+  private:
+    std::shared_ptr<SummaryStatistics> m_stats;
+    ElapsedTime m_elapsed_time;
+  };
+
+private:
+  void OnInvoked() noexcept { m_count.fetch_add(1, std::memory_order_relaxed); 
}
+  lldb_private::StatsDuration m_total_time;
+  const std::string m_impl_type;
+  const std::string m_name;
+  std::atomic<uint64_t> m_count;
+};
+
+typedef std::shared_ptr<SummaryStatistics> SummaryStatisticsSP;
+
+/// A class that wraps a std::map of SummaryStatistics objects behind a mutex.
+class SummaryStatisticsCache {
+public:
+  /// Get the SummaryStatistics object for a given provider name, or insert
+  /// if statistics for that provider is not in the map.
+  SummaryStatisticsSP
+  GetSummaryStatisticsForProviderName(lldb_private::TypeSummaryImpl &provider) 
{
----------------
Jlalond wrote:

@Michael137 I think both the proposal you're approaching and the shared ptr 
flow can work. I think the primary contention will be whose job atomicity will 
be. Considering we're building on top of the established pattern within Elapsed 
time, I prefer SummaryStatistics to be itself thread safe.

As for the cache, I think my primary concern was the double lookup on both the 
`get` and the `update` calls, with our current flow only ever checking twice 
during creation of a new statistics object. I think this is the easiest flow 
because now we only have to think about one lock at runtime, the lock to get or 
insert into the summary cache (and the lock to render it as a json).

I am by far the least experienced person here, so I really only espouse my say 
as the author, but I think for minimum footguns around lifetimes on multiple 
threads, `SummaryStatisticsSP` is the way to go.

https://github.com/llvm/llvm-project/pull/102708
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to