|
|
|||
File indexing completed on 2026-05-10 08:42:45
0001 //===-- Progress.h ----------------------------------------------*- C++ -*-===// 0002 // 0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 0004 // See https://llvm.org/LICENSE.txt for license information. 0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 0006 // 0007 //===----------------------------------------------------------------------===// 0008 0009 #ifndef LLDB_CORE_PROGRESS_H 0010 #define LLDB_CORE_PROGRESS_H 0011 0012 #include "lldb/Host/Alarm.h" 0013 #include "lldb/Utility/Timeout.h" 0014 #include "lldb/lldb-forward.h" 0015 #include "lldb/lldb-types.h" 0016 #include "llvm/ADT/StringMap.h" 0017 #include <atomic> 0018 #include <cstdint> 0019 #include <mutex> 0020 #include <optional> 0021 0022 namespace lldb_private { 0023 0024 /// A Progress indicator helper class. 0025 /// 0026 /// Any potentially long running sections of code in LLDB should report 0027 /// progress so that clients are aware of delays that might appear during 0028 /// debugging. Delays commonly include indexing debug information, parsing 0029 /// symbol tables for object files, downloading symbols from remote 0030 /// repositories, and many more things. 0031 /// 0032 /// The Progress class helps make sure that progress is correctly reported 0033 /// and will always send an initial progress update, updates when 0034 /// Progress::Increment() is called, and also will make sure that a progress 0035 /// completed update is reported even if the user doesn't explicitly cause one 0036 /// to be sent. 0037 /// 0038 /// The progress is reported via a callback whose type is ProgressCallback: 0039 /// 0040 /// typedef void (*ProgressCallback)(uint64_t progress_id, 0041 /// const char *message, 0042 /// uint64_t completed, 0043 /// uint64_t total, 0044 /// void *baton); 0045 /// 0046 /// This callback will always initially be called with \a completed set to zero 0047 /// and \a total set to the total amount specified in the constructor. This is 0048 /// considered the progress start event. As Progress::Increment() is called, 0049 /// the callback will be called as long as the Progress::m_completed has not 0050 /// yet exceeded the Progress::m_total. When the callback is called with 0051 /// Progress::m_completed == Progress::m_total, that is considered a progress 0052 /// completed event. If Progress::m_completed is non-zero and less than 0053 /// Progress::m_total, then this is considered a progress update event. 0054 /// 0055 /// This callback will be called in the destructor if Progress::m_completed is 0056 /// not equal to Progress::m_total with the \a completed set to 0057 /// Progress::m_total. This ensures we always send a progress completed update 0058 /// even if the user does not. 0059 0060 class Progress { 0061 public: 0062 /// Enum to indicate the origin of a progress event, internal or external. 0063 enum class Origin : uint8_t { 0064 eInternal = 0, 0065 eExternal = 1, 0066 }; 0067 0068 /// Construct a progress object that will report information. 0069 /// 0070 /// The constructor will create a unique progress reporting object and 0071 /// immediately send out a progress update by calling the installed callback 0072 /// with \a completed set to zero out of the specified total. 0073 /// 0074 /// @param [in] title The title of this progress activity. 0075 /// 0076 /// @param [in] details Specific information about what the progress report 0077 /// is currently working on. Although not required, if the progress report is 0078 /// updated with Progress::Increment() then this field will be overwritten 0079 /// with the new set of details passed into that function, and the details 0080 /// passed initially will act as an "item 0" for the total set of 0081 /// items being reported on. 0082 /// 0083 /// @param [in] total The total units of work to be done if specified, if 0084 /// set to std::nullopt then an indeterminate progress indicator should be 0085 /// displayed. 0086 /// 0087 /// @param [in] debugger An optional debugger pointer to specify that this 0088 /// progress is to be reported only to specific debuggers. 0089 Progress(std::string title, std::string details = {}, 0090 std::optional<uint64_t> total = std::nullopt, 0091 lldb_private::Debugger *debugger = nullptr, 0092 Timeout<std::nano> minimum_report_time = std::nullopt, 0093 Origin origin = Origin::eInternal); 0094 0095 /// Destroy the progress object. 0096 /// 0097 /// If the progress has not yet sent a completion update, the destructor 0098 /// will send out a notification where the \a completed == m_total. This 0099 /// ensures that we always send out a progress complete notification. 0100 ~Progress(); 0101 0102 /// Increment the progress and send a notification to the installed callback. 0103 /// 0104 /// If incrementing ends up exceeding m_total, m_completed will be updated 0105 /// to match m_total and no subsequent progress notifications will be sent. 0106 /// If no total was specified in the constructor, this function will not do 0107 /// anything nor send any progress updates. 0108 /// 0109 /// @param [in] amount The amount to increment m_completed by. 0110 /// 0111 /// @param [in] an optional message associated with this update. 0112 void Increment(uint64_t amount = 1, 0113 std::optional<std::string> updated_detail = {}); 0114 0115 /// Used to indicate a non-deterministic progress report 0116 static constexpr uint64_t kNonDeterministicTotal = UINT64_MAX; 0117 0118 /// Data belonging to this Progress event that is used for bookkeeping by 0119 /// ProgressManager. 0120 struct ProgressData { 0121 /// The title of the progress activity, also used as a category. 0122 std::string title; 0123 /// A unique integer identifier for progress reporting. 0124 uint64_t progress_id; 0125 /// The optional debugger ID to report progress to. If this has no value 0126 /// then all debuggers will receive this event. 0127 std::optional<lldb::user_id_t> debugger_id; 0128 0129 /// The origin of the progress event, wheter it is internal or external. 0130 Origin origin; 0131 }; 0132 0133 private: 0134 void ReportProgress(); 0135 static std::atomic<uint64_t> g_id; 0136 0137 /// Total amount of work, use a std::nullopt in the constructor for non 0138 /// deterministic progress. 0139 const uint64_t m_total; 0140 0141 // Minimum amount of time between two progress reports. 0142 const Timeout<std::nano> m_minimum_report_time; 0143 0144 /// Data needed by the debugger to broadcast a progress event. 0145 const ProgressData m_progress_data; 0146 0147 /// How much work ([0...m_total]) that has been completed. 0148 std::atomic<uint64_t> m_completed = 0; 0149 0150 /// Time (in nanoseconds since epoch) of the last progress report. 0151 std::atomic<uint64_t> m_last_report_time_ns; 0152 0153 /// Guards non-const non-atomic members of the class. 0154 std::mutex m_mutex; 0155 0156 /// More specific information about the current file being displayed in the 0157 /// report. 0158 std::string m_details; 0159 0160 /// The "completed" value of the last reported event. 0161 std::optional<uint64_t> m_prev_completed; 0162 }; 0163 0164 /// A class used to group progress reports by category. This is done by using a 0165 /// map that maintains a refcount of each category of progress reports that have 0166 /// come in. Keeping track of progress reports this way will be done if a 0167 /// debugger is listening to the eBroadcastBitProgressByCategory broadcast bit. 0168 class ProgressManager { 0169 public: 0170 ProgressManager(); 0171 ~ProgressManager(); 0172 0173 /// Control the refcount of the progress report category as needed. 0174 void Increment(const Progress::ProgressData &); 0175 void Decrement(const Progress::ProgressData &); 0176 0177 static void Initialize(); 0178 static void Terminate(); 0179 static bool Enabled(); 0180 static ProgressManager &Instance(); 0181 0182 protected: 0183 enum class EventType { 0184 Begin, 0185 End, 0186 }; 0187 static void ReportProgress(const Progress::ProgressData &progress_data, 0188 EventType type); 0189 0190 static std::optional<ProgressManager> &InstanceImpl(); 0191 0192 /// Helper function for reporting progress when the alarm in the corresponding 0193 /// entry in the map expires. 0194 void Expire(llvm::StringRef key); 0195 0196 /// Entry used for bookkeeping. 0197 struct Entry { 0198 /// Reference count used for overlapping events. 0199 uint64_t refcount = 0; 0200 0201 /// Data used to emit progress events. 0202 Progress::ProgressData data; 0203 0204 /// Alarm handle used when the refcount reaches zero. 0205 Alarm::Handle handle = Alarm::INVALID_HANDLE; 0206 }; 0207 0208 /// Map used for bookkeeping. 0209 llvm::StringMap<Entry> m_entries; 0210 0211 /// Mutex to provide the map. 0212 std::mutex m_entries_mutex; 0213 0214 /// Alarm instance to coalesce progress events. 0215 Alarm m_alarm; 0216 }; 0217 0218 } // namespace lldb_private 0219 0220 #endif // LLDB_CORE_PROGRESS_H
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|