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#include <utility>
20
21using namespace lldb;
22using namespace lldb_private;
23
24std::atomic<uint64_t> Progress::g_id(0);
25
26// Instrument progress events with signposts when supported.
27static llvm::ManagedStatic<llvm::SignpostEmitter> g_progress_signposts;
28
29Progress::Progress(std::string title, std::string details,
30 std::optional<uint64_t> total,
31 lldb_private::Debugger *debugger,
32 Timeout<std::nano> minimum_report_time,
33 Progress::Origin origin)
34 : m_total(total.value_or(Progress::kNonDeterministicTotal)),
35 m_minimum_report_time(minimum_report_time), m_title(std::move(title)),
37 m_debugger_id(debugger ? std::optional<user_id_t>(debugger->GetID())
38 : std::nullopt),
39 m_origin(origin),
41 std::chrono::nanoseconds(
42 std::chrono::steady_clock::now().time_since_epoch())
43 .count()),
44 m_details(std::move(details)) {
45 std::lock_guard<std::mutex> guard(m_mutex);
47
48 // Start signpost interval right before the meaningful work starts.
49 g_progress_signposts->startInterval(this, m_title);
50}
51
53 // End signpost interval as soon as possible.
54 g_progress_signposts->endInterval(this, m_title);
55
56 // Make sure to always report progress completed when this object is
57 // destructed so it indicates the progress dialog/activity should go away.
58 std::lock_guard<std::mutex> guard(m_mutex);
61}
62
63void Progress::Increment(uint64_t amount,
64 std::optional<std::string> updated_detail) {
65 if (amount == 0)
66 return;
67
68 m_completed.fetch_add(amount, std::memory_order_relaxed);
69
71 using namespace std::chrono;
72
73 nanoseconds now;
74 uint64_t last_report_time_ns =
75 m_last_report_time_ns.load(std::memory_order_relaxed);
76
77 do {
78 now = steady_clock::now().time_since_epoch();
79 if (now < nanoseconds(last_report_time_ns) + *m_minimum_report_time)
80 return; // Too little time has passed since the last report.
81
82 } while (!m_last_report_time_ns.compare_exchange_weak(
83 last_report_time_ns, now.count(), std::memory_order_relaxed,
84 std::memory_order_relaxed));
85 }
86
87 std::lock_guard<std::mutex> guard(m_mutex);
88 if (updated_detail)
89 m_details = std::move(updated_detail.value());
91}
92
94 // NB: Comparisons with optional<T> rely on the fact that std::nullopt is
95 // "smaller" than zero.
97 return; // We've reported completion already.
98
99 uint64_t completed =
100 std::min(m_completed.load(std::memory_order_relaxed), m_total);
101 if (completed < m_prev_completed)
102 return; // An overflow in the m_completed counter. Just ignore these events.
103
104 // Change the category bit if we're an internal or external progress.
105 uint32_t progress_category_bit = m_origin == Progress::Origin::eExternal
108
110 m_total, m_debugger_id, progress_category_bit);
111 m_prev_completed = completed;
112}
static llvm::ManagedStatic< llvm::SignpostEmitter > g_progress_signposts
Definition Progress.cpp:27
A class to manage flag bits.
Definition Debugger.h:100
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:63
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:29
~Progress()
Destroy the progress object.
Definition Progress.cpp:52
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:83