-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[lldb] Add timed callbacks to the MainLoop class #112895
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,27 +7,43 @@ | |
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include "lldb/Host/MainLoopBase.h" | ||
| #include <chrono> | ||
|
|
||
| using namespace lldb; | ||
| using namespace lldb_private; | ||
|
|
||
| void MainLoopBase::AddPendingCallback(const Callback &callback) { | ||
| void MainLoopBase::AddCallback(const Callback &callback, TimePoint point) { | ||
| bool interrupt_needed; | ||
| { | ||
| std::lock_guard<std::mutex> lock{m_callback_mutex}; | ||
| m_pending_callbacks.push_back(callback); | ||
| // We need to interrupt the main thread if this callback is scheduled to | ||
| // execute at an earlier time than the earliest callback registered so far. | ||
| interrupt_needed = m_callbacks.empty() || point < m_callbacks.top().first; | ||
| m_callbacks.emplace(point, callback); | ||
| } | ||
| TriggerPendingCallbacks(); | ||
| if (interrupt_needed) | ||
|
||
| Interrupt(); | ||
| } | ||
|
|
||
| void MainLoopBase::ProcessPendingCallbacks() { | ||
| // Move the callbacks to a local vector to avoid keeping m_pending_callbacks | ||
| // locked throughout the calls. | ||
| std::vector<Callback> pending_callbacks; | ||
| { | ||
| std::lock_guard<std::mutex> lock{m_callback_mutex}; | ||
| pending_callbacks = std::move(m_pending_callbacks); | ||
| } | ||
| void MainLoopBase::ProcessCallbacks() { | ||
| while (true) { | ||
| Callback callback; | ||
| { | ||
| std::lock_guard<std::mutex> lock{m_callback_mutex}; | ||
| if (m_callbacks.empty() || | ||
| std::chrono::steady_clock::now() < m_callbacks.top().first) | ||
| return; | ||
| callback = std::move(m_callbacks.top().second); | ||
| m_callbacks.pop(); | ||
| } | ||
|
|
||
| for (const Callback &callback : pending_callbacks) | ||
| callback(*this); | ||
| } | ||
| } | ||
|
|
||
| std::optional<MainLoopBase::TimePoint> MainLoopBase::GetNextWakeupTime() { | ||
| std::lock_guard<std::mutex> lock(m_callback_mutex); | ||
|
||
| if (m_callbacks.empty()) | ||
| return std::nullopt; | ||
| return m_callbacks.top().first; | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are Nanoseconds here overly precise? Will we imply that callbacks will have nano-second level precision in timing out? I think because this is used for timeouts milliseconds is sufficient
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not likely to be useful, but we do have system APIs which provide nanosecond level resolution, so why not make it available. Users don't have to specify timeouts with a nanosecond level. They can just say
std::chrono::seconds/*or whatever*/(X), and it will be automatically to nanoseconds.Using a lower precision would actually be somewhat unergonomic chrono conversions which lose precision are not implicit. So something like
steady_clock::now()+seconds(2)would not be implicitly convertible to milliseconds if the clock resolution was more than milliseconds (which it usually is).