1 //===-- Progress.h ----------------------------------------------*- 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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLDB_CORE_PROGRESS_H 10 #define LLDB_CORE_PROGRESS_H 11 12 #include "lldb/Utility/ConstString.h" 13 #include "lldb/lldb-types.h" 14 #include <atomic> 15 #include <mutex> 16 17 namespace lldb_private { 18 19 /// A Progress indicator helper class. 20 /// 21 /// Any potentially long running sections of code in LLDB should report 22 /// progress so that clients are aware of delays that might appear during 23 /// debugging. Delays commonly include indexing debug information, parsing 24 /// symbol tables for object files, downloading symbols from remote 25 /// repositories, and many more things. 26 /// 27 /// The Progress class helps make sure that progress is correctly reported 28 /// and will always send an initial progress update, updates when 29 /// Progress::Increment() is called, and also will make sure that a progress 30 /// completed update is reported even if the user doesn't explicitly cause one 31 /// to be sent. 32 /// 33 /// The progress is reported via a callback whose type is ProgressCallback: 34 /// 35 /// typedef void (*ProgressCallback)(uint64_t progress_id, 36 /// const char *message, 37 /// uint64_t completed, 38 /// uint64_t total, 39 /// void *baton); 40 /// 41 /// This callback will always initially be called with "completed" set to zero 42 /// and "total" set to the total amount specified in the contructor. This is 43 /// considered the progress start event. As Progress::Increment() is called, 44 /// the callback will be called as long as the Progress::m_completed has not 45 /// yet exceeded the Progress::m_total. When the callback is called with 46 /// Progress::m_completed == Progress::m_total, that is considered a progress 47 /// completed event. If Progress::m_completed is non-zero and less than 48 /// Progress::m_total, then this is considered a progress update event. 49 /// 50 /// This callback will be called in the destructor if Progress::m_completed is 51 /// not equal to Progress::m_total with the "completed" set to 52 /// Progress::m_total. This ensures we always send a progress completed update 53 /// even if the user does not. 54 55 class Progress { 56 public: 57 /// Construct a progress object that will report information. 58 /// 59 /// The constructor will create a unique progress reporting object and 60 /// immediately send out a progress update by calling the installed callback 61 /// with completed set to zero out of the specified total. 62 /// 63 /// @param [in] title The title of this progress activity. 64 /// 65 /// @param [in] total The total units of work to be done if specified, if 66 /// set to UINT64_MAX then an indeterminate progress indicator should be 67 /// displayed. 68 /// 69 /// @param [in] debugger An optional debugger pointer to specify that this 70 /// progress is to be reported only to specific debuggers. 71 Progress(std::string title, uint64_t total = UINT64_MAX, 72 lldb_private::Debugger *debugger = nullptr); 73 74 /// Destroy the progress object. 75 /// 76 /// If the progress has not yet sent a completion update, the destructor 77 /// will send out a notification where the completed == m_total. This ensures 78 /// that we always send out a progress complete notification. 79 ~Progress(); 80 81 /// Increment the progress and send a notification to the intalled callback. 82 /// 83 /// If incrementing ends up exceeding m_total, m_completed will be updated 84 /// to match m_total and no subsequent progress notifications will be sent. 85 /// If no total was specified in the constructor, this function will not do 86 /// anything nor send any progress updates. 87 /// 88 /// @param [in] amount The amount to increment m_completed by. 89 void Increment(uint64_t amount = 1); 90 91 private: 92 void ReportProgress(); 93 static std::atomic<uint64_t> g_id; 94 /// The title of the progress activity. 95 std::string m_title; 96 std::mutex m_mutex; 97 /// A unique integer identifier for progress reporting. 98 const uint64_t m_id; 99 /// How much work ([0...m_total]) that has been completed. 100 uint64_t m_completed; 101 /// Total amount of work, UINT64_MAX for non deterministic progress. 102 const uint64_t m_total; 103 /// The optional debugger ID to report progress to. If this has no value then 104 /// all debuggers will receive this event. 105 llvm::Optional<lldb::user_id_t> m_debugger_id; 106 /// Set to true when progress has been reported where m_completed == m_total 107 /// to ensure that we don't send progress updates after progress has 108 /// completed. 109 bool m_complete = false; 110 }; 111 112 } // namespace lldb_private 113 114 #endif // LLDB_CORE_PROGRESS_H 115