brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.7 KiB · 9dfed4c Raw
166 lines · c
1//===-- ProgressEvent.cpp ---------------------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLDB_TOOLS_LLDB_DAP_PROGRESS_EVENT_H10#define LLDB_TOOLS_LLDB_DAP_PROGRESS_EVENT_H11 12#include <atomic>13#include <chrono>14#include <mutex>15#include <optional>16#include <queue>17#include <thread>18 19#include "llvm/Support/JSON.h"20 21namespace lldb_dap {22 23enum ProgressEventType { progressStart, progressUpdate, progressEnd };24 25class ProgressEvent;26using ProgressEventReportCallback = std::function<void(ProgressEvent &)>;27 28class ProgressEvent {29public:30  /// Actual constructor to use that returns an optional, as the event might be31  /// not apt for the IDE, e.g. an unnamed start event, or a redundant one.32  ///33  /// \param[in] progress_id34  ///   ID for this event.35  ///36  /// \param[in] message37  ///   Message to display in the UI. Required for start events.38  ///39  /// \param[in] completed40  ///   Number of jobs completed.41  ///42  /// \param[in] total43  ///   Total number of jobs, or \b UINT64_MAX if not determined.44  ///45  /// \param[in] prev_event46  ///   Previous event if this one is an update. If \b nullptr, then a start47  ///   event will be created.48  static std::optional<ProgressEvent>49  Create(uint64_t progress_id, std::optional<llvm::StringRef> message,50         uint64_t completed, uint64_t total,51         const ProgressEvent *prev_event = nullptr);52 53  llvm::json::Value ToJSON() const;54 55  /// \return56  ///       \b true if two event messages would result in the same event for the57  ///       IDE, e.g. same rounded percentage.58  bool EqualsForIDE(const ProgressEvent &other) const;59 60  llvm::StringRef GetEventName() const;61 62  ProgressEventType GetEventType() const;63 64  /// Report this progress event to the provided callback only if enough time65  /// has passed since the creation of the event and since the previous reported66  /// update.67  bool Report(ProgressEventReportCallback callback);68 69  bool Reported() const;70 71private:72  ProgressEvent(uint64_t progress_id, std::optional<llvm::StringRef> message,73                uint64_t completed, uint64_t total,74                const ProgressEvent *prev_event);75 76  uint64_t m_progress_id;77  std::string m_message;78  ProgressEventType m_event_type;79  std::optional<uint32_t> m_percentage;80  std::chrono::duration<double> m_creation_time =81      std::chrono::system_clock::now().time_since_epoch();82  std::chrono::duration<double> m_minimum_allowed_report_time;83  bool m_reported = false;84};85 86/// Class that keeps the start event and its most recent update.87/// It controls when the event should start being reported to the IDE.88class ProgressEventManager {89public:90  ProgressEventManager(const ProgressEvent &start_event,91                       ProgressEventReportCallback report_callback);92 93  /// Report the start event and the most recent update if the event has lasted94  /// for long enough.95  ///96  /// \return97  ///     \b false if the event hasn't finished and hasn't reported anything98  ///     yet.99  bool ReportIfNeeded();100 101  /// Receive a new progress event for the start event and try to report it if102  /// appropriate.103  void Update(uint64_t progress_id, llvm::StringRef message, uint64_t completed,104              uint64_t total);105 106  /// \return107  ///     \b true if a \a progressEnd event has been notified. There's no108  ///     need to try to report manually an event that has finished.109  bool Finished() const;110 111  const ProgressEvent &GetMostRecentEvent() const;112 113private:114  ProgressEvent m_start_event;115  std::optional<ProgressEvent> m_last_update_event;116  bool m_finished;117  ProgressEventReportCallback m_report_callback;118};119 120using ProgressEventManagerSP = std::shared_ptr<ProgressEventManager>;121 122/// Class that filters out progress event messages that shouldn't be reported123/// to the IDE, because they are invalid, they carry no new information, or they124/// don't last long enough.125///126/// We need to limit the amount of events that are sent to the IDE, as they slow127/// the render thread of the UI user, and they end up spamming the DAP128/// connection, which also takes some processing time out of the IDE.129class ProgressEventReporter {130public:131  /// \param[in] report_callback132  ///     Function to invoke to report the event to the IDE.133  explicit ProgressEventReporter(ProgressEventReportCallback report_callback);134 135  ProgressEventReporter(const ProgressEventReporter &) = delete;136  ProgressEventReporter(ProgressEventReporter &&) = delete;137  ProgressEventReporter &operator=(const ProgressEventReporter &) = delete;138  ProgressEventReporter &operator=(ProgressEventReporter &&) = delete;139  ~ProgressEventReporter();140 141  /// Add a new event to the internal queue and report the event if142  /// appropriate.143  void Push(uint64_t progress_id, const char *message, uint64_t completed,144            uint64_t total);145 146private:147  /// Report to the IDE events that haven't been reported to the IDE and have148  /// lasted long enough.149  void ReportStartEvents();150 151  ProgressEventReportCallback m_report_callback;152  std::map<uint64_t, ProgressEventManagerSP> m_event_managers;153  /// Queue of start events in chronological order154  std::queue<ProgressEventManagerSP> m_unreported_start_events;155  /// Thread used to invoke \a ReportStartEvents periodically.156  std::thread m_thread;157  std::atomic<bool> m_thread_should_exit;158  /// Mutex that prevents running \a Push and \a ReportStartEvents159  /// simultaneously, as both read and modify the same underlying objects.160  std::mutex m_mutex;161};162 163} // namespace lldb_dap164 165#endif // LLDB_TOOLS_LLDB_DAP_PROGRESS_EVENT_H166