Mir

Merge lp:~kdub/mir/queueing-schedule into lp:mir

Proposed by Kevin DuBois
Status: Merged
Approved by: Kevin DuBois
Approved revision: no longer in the source branch.
Merged at revision: 2777
Proposed branch: lp:~kdub/mir/queueing-schedule
Merge into: lp:mir
Diff against target: 215 lines (+179/-0)
5 files modified
src/server/compositor/CMakeLists.txt (+1/-0)
src/server/compositor/queueing_schedule.cpp (+49/-0)
src/server/compositor/queueing_schedule.h (+43/-0)
tests/unit-tests/compositor/CMakeLists.txt (+1/-0)
tests/unit-tests/compositor/test_queueing_schedule.cpp (+85/-0)
To merge this branch: bzr merge lp:~kdub/mir/queueing-schedule
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Cemil Azizoglu (community) Approve
Chris Halse Rogers Approve
Robert Carr (community) Approve
Alexandros Frantzis (community) Approve
Review via email: mp+265304@code.launchpad.net

Commit message

compositor: add a yet-unused schedule for queueing (swapinterval 1) clients (ie, those that want all their submitted buffers to appear onscreen)

Description of the change

compositor: add a yet-unused schedule for queueing (swapinterval 1) clients (ie, those that want all their submitted buffers to appear onscreen)

note:
1) In the current algorithm, a swapinterval1 client will drop frames periodically according to its FrameDropPolicy to help out qt5. This feature isn't implemented yet... Either the serverside policy or the client (via a cancel rpc call) could provide this feature via the cancel() call.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

Looks good.

Nits:

44 + std::unique_lock<decltype(mutex)> lk(mutex);

We could use lock_guard<> instead of the more unique_lock<>.

202 + for(auto i = 0u; i < num_buffers; i++)
203 + if (i & 1) schedule.schedule(buffers[i]);
204 + for(auto i = 0u; i < num_buffers; i++)
205 + if (!(i & 1)) schedule.schedule(buffers[i]);

209 + EXPECT_THAT(drain_queue(),
210 + ElementsAre(buffers[1], buffers[3], buffers[0], buffers[2], buffers[4]));

Since our expectation depends on num_buffers = 5, we don't gain anything for this test by introducing more general logic in our scheduling. We could have just have, e.g.:

std::vector<> buffer_schedule{buffers[1], buffers[3], buffers[0], buffers[2], buffers[4]};
for (auto b : buffer_schedule) schedule.schedule(b);
EXPECT_THAT(drain_queue(), ContainerEq(buffer_schedule));

Alternatively, we could keep the scheduling logic but make our expectation independent of the value of num_buffers.

review: Approve
Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

"We could use lock_guard<> instead of the more unique_lock<>."

... of the more expensive unique_lock<>

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Chris Halse Rogers (raof) wrote :

As with https://code.launchpad.net/~kdub/mir/dropping-schedule/+merge/265303/comments/666132, cancel() races with anything_scheduled().

Perhaps the Schedule shoud instead be called the BufferQueue, and should have the current_buffer()/advance_buffer() semantics I suggested in https://code.launchpad.net/~kdub/mir/multimonitor-arbiter/+merge/265301/comments/666115 ?

review: Needs Fixing
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Robert Carr (robertcarr) wrote :

I have the thought that these might be the kind of unit tests that should be implemented as guides and then thrown away...it's strange that they are larger than the implementation.

Seems ok to me though.

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Chris Halse Rogers (raof) wrote :

Seems a reasonable transition step.

review: Approve
Revision history for this message
Cemil Azizoglu (cemil-azizoglu) wrote :

Ok

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/server/compositor/CMakeLists.txt'
2--- src/server/compositor/CMakeLists.txt 2015-07-23 14:07:02 +0000
3+++ src/server/compositor/CMakeLists.txt 2015-07-23 19:21:25 +0000
4@@ -19,6 +19,7 @@
5 recently_used_cache.cpp
6 multi_monitor_arbiter.cpp
7 buffer_map.cpp
8+ queueing_schedule.cpp
9 )
10
11 ADD_LIBRARY(
12
13=== added file 'src/server/compositor/queueing_schedule.cpp'
14--- src/server/compositor/queueing_schedule.cpp 1970-01-01 00:00:00 +0000
15+++ src/server/compositor/queueing_schedule.cpp 2015-07-23 19:21:25 +0000
16@@ -0,0 +1,49 @@
17+/*
18+ * Copyright © 2015 Canonical Ltd.
19+ *
20+ * This program is free software: you can redistribute it and/or modify it
21+ * under the terms of the GNU General Public License version 3,
22+ * as published by the Free Software Foundation.
23+ *
24+ * This program is distributed in the hope that it will be useful,
25+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
26+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27+ * GNU General Public License for more details.
28+ *
29+ * You should have received a copy of the GNU General Public License
30+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
31+ *
32+ * Authored by: Kevin DuBois <kevin.dubois@canonical.com>
33+ */
34+
35+#include "queueing_schedule.h"
36+#include <boost/throw_exception.hpp>
37+#include <algorithm>
38+
39+namespace mc = mir::compositor;
40+namespace mg = mir::graphics;
41+
42+void mc::QueueingSchedule::schedule(std::shared_ptr<graphics::Buffer> const& buffer)
43+{
44+ std::lock_guard<decltype(mutex)> lk(mutex);
45+ auto it = std::find(queue.begin(), queue.end(), buffer);
46+ if (it != queue.end())
47+ queue.erase(it);
48+ queue.emplace_back(buffer);
49+}
50+
51+bool mc::QueueingSchedule::anything_scheduled()
52+{
53+ std::lock_guard<decltype(mutex)> lk(mutex);
54+ return !queue.empty();
55+}
56+
57+std::shared_ptr<mg::Buffer> mc::QueueingSchedule::next_buffer()
58+{
59+ std::lock_guard<decltype(mutex)> lk(mutex);
60+ if (queue.empty())
61+ BOOST_THROW_EXCEPTION(std::logic_error("no buffer scheduled"));
62+ auto buffer = queue.front();
63+ queue.pop_front();
64+ return buffer;
65+}
66
67=== added file 'src/server/compositor/queueing_schedule.h'
68--- src/server/compositor/queueing_schedule.h 1970-01-01 00:00:00 +0000
69+++ src/server/compositor/queueing_schedule.h 2015-07-23 19:21:25 +0000
70@@ -0,0 +1,43 @@
71+/*
72+ * Copyright © 2015 Canonical Ltd.
73+ *
74+ * This program is free software: you can redistribute it and/or modify it
75+ * under the terms of the GNU General Public License version 3,
76+ * as published by the Free Software Foundation.
77+ *
78+ * This program is distributed in the hope that it will be useful,
79+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
80+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
81+ * GNU General Public License for more details.
82+ *
83+ * You should have received a copy of the GNU General Public License
84+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
85+ *
86+ * Authored by: Kevin DuBois <kevin.dubois@canonical.com>
87+ */
88+
89+#ifndef MIR_COMPOSITOR_QUEUEING_SCHEDULE_H_
90+#define MIR_COMPOSITOR_QUEUEING_SCHEDULE_H_
91+#include <memory>
92+#include <deque>
93+#include <mutex>
94+
95+namespace mir
96+{
97+namespace graphics { class Buffer; }
98+namespace compositor
99+{
100+class QueueingSchedule
101+{
102+public:
103+ void schedule(std::shared_ptr<graphics::Buffer> const& buffer);
104+ bool anything_scheduled();
105+ std::shared_ptr<graphics::Buffer> next_buffer();
106+
107+private:
108+ std::mutex mutable mutex;
109+ std::deque<std::shared_ptr<graphics::Buffer>> queue;
110+};
111+}
112+}
113+#endif /* MIR_COMPOSITOR_QUEUEING_SCHEDULE_H_ */
114
115=== modified file 'tests/unit-tests/compositor/CMakeLists.txt'
116--- tests/unit-tests/compositor/CMakeLists.txt 2015-07-23 14:07:02 +0000
117+++ tests/unit-tests/compositor/CMakeLists.txt 2015-07-23 19:21:25 +0000
118@@ -13,6 +13,7 @@
119 ${CMAKE_CURRENT_SOURCE_DIR}/test_timeout_frame_dropping_policy.cpp
120 ${CMAKE_CURRENT_SOURCE_DIR}/test_multi_monitor_arbiter.cpp
121 ${CMAKE_CURRENT_SOURCE_DIR}/test_client_buffers.cpp
122+ ${CMAKE_CURRENT_SOURCE_DIR}/test_queueing_schedule.cpp
123 )
124
125 set(UNIT_TEST_SOURCES ${UNIT_TEST_SOURCES} PARENT_SCOPE)
126
127=== added file 'tests/unit-tests/compositor/test_queueing_schedule.cpp'
128--- tests/unit-tests/compositor/test_queueing_schedule.cpp 1970-01-01 00:00:00 +0000
129+++ tests/unit-tests/compositor/test_queueing_schedule.cpp 2015-07-23 19:21:25 +0000
130@@ -0,0 +1,85 @@
131+/*
132+ * Copyright © 2015 Canonical Ltd.
133+ *
134+ * This program is free software: you can redistribute it and/or modify
135+ * it under the terms of the GNU General Public License version 3 as
136+ * published by the Free Software Foundation.
137+ *
138+ * This program is distributed in the hope that it will be useful,
139+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
140+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
141+ * GNU General Public License for more details.
142+ *
143+ * You should have received a copy of the GNU General Public License
144+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
145+ *
146+ * Authored by: Kevin DuBois <kevin.dubois@canonical.com>
147+ */
148+
149+#include "src/server/compositor/queueing_schedule.h"
150+#include "mir/test/doubles/stub_buffer.h"
151+#include <gtest/gtest.h>
152+
153+using namespace testing;
154+namespace mtd = mir::test::doubles;
155+namespace mg = mir::graphics;
156+namespace mc = mir::compositor;
157+
158+namespace
159+{
160+struct QueueingSchedule : Test
161+{
162+ QueueingSchedule()
163+ {
164+ for(auto i = 0u; i < num_buffers; i++)
165+ buffers.emplace_back(std::make_shared<mtd::StubBuffer>());
166+ }
167+ unsigned int const num_buffers{5};
168+ std::vector<std::shared_ptr<mg::Buffer>> buffers;
169+
170+ mc::QueueingSchedule schedule;
171+ std::vector<std::shared_ptr<mg::Buffer>> drain_queue()
172+ {
173+ std::vector<std::shared_ptr<mg::Buffer>> scheduled_buffers;
174+ while(schedule.anything_scheduled())
175+ scheduled_buffers.emplace_back(schedule.next_buffer());
176+ return scheduled_buffers;
177+ }
178+};
179+}
180+
181+TEST_F(QueueingSchedule, throws_if_no_buffers)
182+{
183+ EXPECT_FALSE(schedule.anything_scheduled());
184+ EXPECT_THROW({
185+ schedule.next_buffer();
186+ }, std::logic_error);
187+}
188+
189+TEST_F(QueueingSchedule, queues_buffers_up)
190+{
191+ EXPECT_FALSE(schedule.anything_scheduled());
192+
193+ std::vector<std::shared_ptr<mg::Buffer>> scheduled_buffers {
194+ buffers[1], buffers[3], buffers[0], buffers[2], buffers[4]
195+ };
196+
197+ for (auto& buffer : scheduled_buffers)
198+ schedule.schedule(buffer);
199+
200+ EXPECT_TRUE(schedule.anything_scheduled());
201+
202+ EXPECT_THAT(drain_queue(), ContainerEq(scheduled_buffers));
203+
204+ EXPECT_FALSE(schedule.anything_scheduled());
205+}
206+
207+TEST_F(QueueingSchedule, queuing_the_same_buffer_moves_it_to_front_of_queue)
208+{
209+ for(auto i = 0u; i < num_buffers; i++)
210+ schedule.schedule(buffers[i]);
211+ schedule.schedule(buffers[0]);
212+
213+ EXPECT_THAT(drain_queue(),
214+ ElementsAre(buffers[1], buffers[2], buffers[3], buffers[4], buffers[0]));
215+}

Subscribers

People subscribed via source and target branches