LLDB mainline
Progress.cpp
Go to the documentation of this file.
1//===-- Progress.cpp ------------------------------------------------------===//
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
10
11#include "lldb/Core/Debugger.h"
13#include "llvm/Support/Signposts.h"
14#include <atomic>
15#include <chrono>
16#include <cstdint>
17#include <mutex>
18#include <optional>
19
20using namespace lldb;
21using namespace lldb_private;
22
23std::atomic<uint64_t> Progress::g_id(0);
24
25// Instrument progress events with signposts when supported.
26static llvm::ManagedStatic<llvm::SignpostEmitter> g_progress_signposts;
27
28Progress::Progress(std::string title, std::string details,
29 std::optional<uint64_t> total,
30 lldb_private::Debugger *debugger,
31 Timeout<std::nano> minimum_report_time,
32 Progress::Origin origin)
33 : m_total(total.value_or(Progress::kNonDeterministicTotal)),
34 m_minimum_report_time(minimum_report_time), m_title(title),
36 m_debugger_id(debugger ? std::optional<user_id_t>(debugger->GetID())
37 : std::nullopt),
38 m_origin(origin),
40 std::chrono::nanoseconds(
41 std::chrono::steady_clock::now().time_since_epoch())
42 .count()),
43 m_details(std::move(details)) {
44 std::lock_guard<std::mutex> guard(m_mutex);
46
47 // Start signpost interval right before the meaningful work starts.
48 g_progress_signposts->startInterval(this, m_title);
49}
50
52 // End signpost interval as soon as possible.
53 g_progress_signposts->endInterval(this, m_title);
54
55 // Make sure to always report progress completed when this object is
56 // destructed so it indicates the progress dialog/activity should go away.
57 std::lock_guard<std::mutex> guard(m_mutex);
60}
61
62void Progress::Increment(uint64_t amount,
63 std::optional<std::string> updated_detail) {
64 if (amount == 0)
65 return;
66
67 m_completed.fetch_add(amount, std::memory_order_relaxed);
68
70 using namespace std::chrono;
71
72 nanoseconds now;
73 uint64_t last_report_time_ns =
74 m_last_report_time_ns.load(std::memory_order_relaxed);
75
76 do {
77 now = steady_clock::now().time_since_epoch();
78 if (now < nanoseconds(last_report_time_ns) + *m_minimum_report_time)
79 return; // Too little time has passed since the last report.
80
81 } while (!m_last_report_time_ns.compare_exchange_weak(
82 last_report_time_ns, now.count(), std::memory_order_relaxed,
83 std::memory_order_relaxed));
84 }
85
86 std::lock_guard<std::mutex> guard(m_mutex);
87 if (updated_detail)
88 m_details = std::move(updated_detail.value());
90}
91
93 // NB: Comparisons with optional<T> rely on the fact that std::nullopt is
94 // "smaller" than zero.
96 return; // We've reported completion already.
97
98 uint64_t completed =
99 std::min(m_completed.load(std::memory_order_relaxed), m_total);
100 if (completed < m_prev_completed)
101 return; // An overflow in the m_completed counter. Just ignore these events.
102
103 // Change the category bit if we're an internal or external progress.
104 uint32_t progress_category_bit = m_origin == Progress::Origin::eExternal
107
109 m_total, m_debugger_id, progress_category_bit);
110 m_prev_completed = completed;
111}
static llvm::ManagedStatic< llvm::SignpostEmitter > g_progress_signposts
Definition Progress.cpp:26
A class to manage flag bits.
Definition Debugger.h:80
static void ReportProgress(uint64_t progress_id, std::string title, std::string details, uint64_t completed, uint64_t total, std::optional< lldb::user_id_t > debugger_id, uint32_t progress_category_bit=lldb::eBroadcastBitProgress)
Report progress events.
const Timeout< std::nano > m_minimum_report_time
Definition Progress.h:131
const std::optional< lldb::user_id_t > m_debugger_id
The optional debugger ID to report progress to.
Definition Progress.h:141
const std::string m_title
The title of the progress activity, also used as a category.
Definition Progress.h:134
void Increment(uint64_t amount=1, std::optional< std::string > updated_detail={})
Increment the progress and send a notification to the installed callback.
Definition Progress.cpp:62
static std::atomic< uint64_t > g_id
Definition Progress.h:124
const Origin m_origin
The origin of the progress event, whether it is internal or external.
Definition Progress.h:144
std::atomic< uint64_t > m_last_report_time_ns
Time (in nanoseconds since epoch) of the last progress report.
Definition Progress.h:150
std::string m_details
More specific information about the current file being displayed in the report.
Definition Progress.h:157
Origin
Enum to indicate the origin of a progress event, internal or external.
Definition Progress.h:63
static constexpr uint64_t kNonDeterministicTotal
Used to indicate a non-deterministic progress report.
Definition Progress.h:116
std::mutex m_mutex
Guards non-const non-atomic members of the class.
Definition Progress.h:153
const uint64_t m_progress_id
A unique integer identifier for progress reporting.
Definition Progress.h:137
std::atomic< uint64_t > m_completed
How much work ([0...m_total]) that has been completed.
Definition Progress.h:147
std::optional< uint64_t > m_prev_completed
The "completed" value of the last reported event.
Definition Progress.h:160
Progress(std::string title, std::string details={}, std::optional< uint64_t > total=std::nullopt, lldb_private::Debugger *debugger=nullptr, Timeout< std::nano > minimum_report_time=std::nullopt, Origin origin=Origin::eInternal)
Construct a progress object that will report information.
Definition Progress.cpp:28
~Progress()
Destroy the progress object.
Definition Progress.cpp:51
const uint64_t m_total
Total amount of work, use a std::nullopt in the constructor for non deterministic progress.
Definition Progress.h:128
A class that represents a running process on the host machine.
@ eBroadcastBitExternalProgress
@ eBroadcastBitProgress
uint64_t user_id_t
Definition lldb-types.h:82