Commit f392e62f authored by Tom Anderson's avatar Tom Anderson Committed by Chromium LUCI CQ

[XProto] Switch event queue from a std::list to a base::circular_deque

This is needed as a prerequisite for [1].  It also improves performance
a bit by replacing a node-based data structure with a flat one.

[1] https://chromium-review.googlesource.com/c/chromium/src/+/2622521

Change-Id: Ibe2e522f6c131876ed73793305524c25b42ab910
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2625784
Commit-Queue: Thomas Anderson <thomasanderson@chromium.org>
Reviewed-by: default avatarScott Violet <sky@chromium.org>
Cr-Commit-Position: refs/heads/master@{#844303}
parent 44711001
...@@ -305,16 +305,14 @@ int CoalescePendingMotionEvents(const x11::Event& x11_event, ...@@ -305,16 +305,14 @@ int CoalescePendingMotionEvents(const x11::Event& x11_event,
conn->ReadResponses(); conn->ReadResponses();
if (motion) { if (motion) {
for (auto it = conn->events().begin(); it != conn->events().end();) { for (auto& next_event : conn->events()) {
const auto& next_event = *it;
// Discard all but the most recent motion event that targets the same // Discard all but the most recent motion event that targets the same
// window with unchanged state. // window with unchanged state.
const auto* next_motion = next_event.As<x11::MotionNotifyEvent>(); const auto* next_motion = next_event.As<x11::MotionNotifyEvent>();
if (next_motion && next_motion->event == motion->event && if (next_motion && next_motion->event == motion->event &&
next_motion->child == motion->child && next_motion->child == motion->child &&
next_motion->state == motion->state) { next_motion->state == motion->state) {
*last_event = std::move(*it); *last_event = std::move(next_event);
it = conn->events().erase(it);
} else { } else {
break; break;
} }
...@@ -324,8 +322,8 @@ int CoalescePendingMotionEvents(const x11::Event& x11_event, ...@@ -324,8 +322,8 @@ int CoalescePendingMotionEvents(const x11::Event& x11_event,
device->opcode == x11::Input::DeviceEvent::TouchUpdate); device->opcode == x11::Input::DeviceEvent::TouchUpdate);
auto* ddmx11 = ui::DeviceDataManagerX11::GetInstance(); auto* ddmx11 = ui::DeviceDataManagerX11::GetInstance();
for (auto it = conn->events().begin(); it != conn->events().end();) { for (auto& event : conn->events()) {
auto* next_device = it->As<x11::Input::DeviceEvent>(); auto* next_device = event.As<x11::Input::DeviceEvent>();
if (!next_device) if (!next_device)
break; break;
...@@ -336,13 +334,13 @@ int CoalescePendingMotionEvents(const x11::Event& x11_event, ...@@ -336,13 +334,13 @@ int CoalescePendingMotionEvents(const x11::Event& x11_event,
// always be at least one pending. // always be at least one pending.
if (!ui::TouchFactory::GetInstance()->ShouldProcessDeviceEvent( if (!ui::TouchFactory::GetInstance()->ShouldProcessDeviceEvent(
*next_device)) { *next_device)) {
it = conn->events().erase(it); event = x11::Event();
continue; continue;
} }
if (next_device->opcode == device->opcode && if (next_device->opcode == device->opcode &&
!ddmx11->IsCMTGestureEvent(*it) && !ddmx11->IsCMTGestureEvent(event) &&
ddmx11->GetScrollClassEventDetail(*it) == SCROLL_TYPE_NO_SCROLL) { ddmx11->GetScrollClassEventDetail(event) == SCROLL_TYPE_NO_SCROLL) {
// Confirm that the motion event is targeted at the same window // Confirm that the motion event is targeted at the same window
// and that no buttons or modifiers have changed. // and that no buttons or modifiers have changed.
if (device->event == next_device->event && if (device->event == next_device->event &&
...@@ -353,12 +351,12 @@ int CoalescePendingMotionEvents(const x11::Event& x11_event, ...@@ -353,12 +351,12 @@ int CoalescePendingMotionEvents(const x11::Event& x11_event,
device->mods.latched == next_device->mods.latched && device->mods.latched == next_device->mods.latched &&
device->mods.locked == next_device->mods.locked && device->mods.locked == next_device->mods.locked &&
device->mods.effective == next_device->mods.effective) { device->mods.effective == next_device->mods.effective) {
*last_event = std::move(*it); *last_event = std::move(event);
it = conn->events().erase(it);
num_coalesced++; num_coalesced++;
continue; continue;
} }
} }
break; break;
} }
} }
......
...@@ -201,8 +201,9 @@ x11::Time X11EventSource::GetCurrentServerTime() { ...@@ -201,8 +201,9 @@ x11::Time X11EventSource::GetCurrentServerTime() {
}; };
auto& events = connection_->events(); auto& events = connection_->events();
events.erase(std::remove_if(events.begin(), events.end(), pred), auto it = std::find_if(events.begin(), events.end(), pred);
events.end()); if (it != events.end())
*it = x11::Event();
return time; return time;
} }
......
...@@ -287,6 +287,15 @@ bool Connection::HasNextResponse() { ...@@ -287,6 +287,15 @@ bool Connection::HasNextResponse() {
return true; return true;
} }
bool Connection::HasNextEvent() {
while (!events_.empty()) {
if (events_.front().Initialized())
return true;
events_.pop_front();
}
return false;
}
int Connection::GetFd() { int Connection::GetFd() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return Ready() ? xcb_get_file_descriptor(XcbConnection()) : -1; return Ready() ? xcb_get_file_descriptor(XcbConnection()) : -1;
...@@ -355,7 +364,7 @@ void Connection::ReadResponses() { ...@@ -355,7 +364,7 @@ void Connection::ReadResponses() {
Event Connection::WaitForNextEvent() { Event Connection::WaitForNextEvent() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!events_.empty()) { if (HasNextEvent()) {
Event event = std::move(events_.front()); Event event = std::move(events_.front());
events_.pop_front(); events_.pop_front();
return event; return event;
...@@ -369,7 +378,7 @@ Event Connection::WaitForNextEvent() { ...@@ -369,7 +378,7 @@ Event Connection::WaitForNextEvent() {
bool Connection::HasPendingResponses() { bool Connection::HasPendingResponses() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return !events_.empty() || HasNextResponse(); return HasNextEvent() || HasNextResponse();
} }
const Connection::VisualInfo* Connection::GetVisualInfoFromId( const Connection::VisualInfo* Connection::GetVisualInfoFromId(
...@@ -405,7 +414,7 @@ void Connection::DetachFromSequence() { ...@@ -405,7 +414,7 @@ void Connection::DetachFromSequence() {
bool Connection::Dispatch() { bool Connection::Dispatch() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (HasNextResponse() && !events_.empty()) { if (HasNextResponse() && HasNextEvent()) {
auto next_response_sequence = first_request_id_; auto next_response_sequence = first_request_id_;
auto next_event_sequence = events_.front().sequence(); auto next_event_sequence = events_.front().sequence();
...@@ -418,7 +427,7 @@ bool Connection::Dispatch() { ...@@ -418,7 +427,7 @@ bool Connection::Dispatch() {
ProcessNextEvent(); ProcessNextEvent();
} else if (HasNextResponse()) { } else if (HasNextResponse()) {
ProcessNextResponse(); ProcessNextResponse();
} else if (!events_.empty()) { } else if (HasNextEvent()) {
ProcessNextEvent(); ProcessNextEvent();
} else { } else {
return false; return false;
...@@ -488,7 +497,7 @@ void Connection::InitRootDepthAndVisual() { ...@@ -488,7 +497,7 @@ void Connection::InitRootDepthAndVisual() {
void Connection::ProcessNextEvent() { void Connection::ProcessNextEvent() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!events_.empty()); DCHECK(HasNextEvent());
Event event = std::move(events_.front()); Event event = std::move(events_.front());
events_.pop_front(); events_.pop_front();
......
...@@ -5,9 +5,6 @@ ...@@ -5,9 +5,6 @@
#ifndef UI_GFX_X_CONNECTION_H_ #ifndef UI_GFX_X_CONNECTION_H_
#define UI_GFX_X_CONNECTION_H_ #define UI_GFX_X_CONNECTION_H_
#include <list>
#include <queue>
#include "base/callback.h" #include "base/callback.h"
#include "base/component_export.h" #include "base/component_export.h"
#include "base/containers/circular_deque.h" #include "base/containers/circular_deque.h"
...@@ -183,8 +180,10 @@ class COMPONENT_EXPORT(X11) Connection : public XProto, ...@@ -183,8 +180,10 @@ class COMPONENT_EXPORT(X11) Connection : public XProto,
uint32_t KeycodeToKeysym(KeyCode keycode, uint32_t modifiers) const; uint32_t KeycodeToKeysym(KeyCode keycode, uint32_t modifiers) const;
// Access the event buffer. Clients can add, delete, or modify events. // Access the event buffer. Clients may modify the queue, including
std::list<Event>& events() { // "deleting" events by setting events[i] = x11::Event(), which will
// guarantee all calls to x11::Event::As() will return nullptr.
base::circular_deque<Event>& events() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return events_; return events_;
} }
...@@ -268,6 +267,8 @@ class COMPONENT_EXPORT(X11) Connection : public XProto, ...@@ -268,6 +267,8 @@ class COMPONENT_EXPORT(X11) Connection : public XProto,
bool HasNextResponse(); bool HasNextResponse();
bool HasNextEvent();
// Creates a new Request and adds it to the end of the queue. // Creates a new Request and adds it to the end of the queue.
// |request_name_for_tracing| must be valid until the response is // |request_name_for_tracing| must be valid until the response is
// dispatched; currently the string values are only stored in .rodata, so // dispatched; currently the string values are only stored in .rodata, so
...@@ -312,7 +313,7 @@ class COMPONENT_EXPORT(X11) Connection : public XProto, ...@@ -312,7 +313,7 @@ class COMPONENT_EXPORT(X11) Connection : public XProto,
std::unique_ptr<KeyboardState> keyboard_state_; std::unique_ptr<KeyboardState> keyboard_state_;
std::list<Event> events_; base::circular_deque<Event> events_;
base::ObserverList<EventObserver>::Unchecked event_observers_; base::ObserverList<EventObserver>::Unchecked event_observers_;
......
...@@ -70,6 +70,8 @@ class COMPONENT_EXPORT(X11) Event { ...@@ -70,6 +70,8 @@ class COMPONENT_EXPORT(X11) Event {
*window_ = window; *window_ = window;
} }
bool Initialized() const { return deleter_; }
private: private:
friend void ReadEvent(Event* event, friend void ReadEvent(Event* event,
Connection* connection, Connection* connection,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment