Mir

Merge lp:~mir-team/mir/fix-1315302 into lp:mir

Proposed by Alberto Aguirre
Status: Merged
Approved by: Alberto Aguirre
Approved revision: no longer in the source branch.
Merged at revision: 1606
Proposed branch: lp:~mir-team/mir/fix-1315302
Merge into: lp:mir
Diff against target: 140 lines (+37/-34)
3 files modified
src/server/compositor/buffer_queue.cpp (+7/-11)
src/server/compositor/buffer_queue.h (+4/-2)
tests/unit-tests/compositor/test_buffer_queue.cpp (+26/-21)
To merge this branch: bzr merge lp:~mir-team/mir/fix-1315302
Reviewer Review Type Date Requested Status
Cemil Azizoglu (community) Approve
Alan Griffiths Approve
PS Jenkins bot (community) continuous-integration Approve
Daniel van Vugt Approve
Review via email: mp+218348@code.launchpad.net

Commit message

Ensure that if you have multiple client_acquire's outstanding, they each
get called back, eventually (LP: #1315302)

To post a comment you must log in.
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Verified the regression test fails without the fix. Works with it. Looks reasonable.

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

OK

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

Looks good.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/server/compositor/buffer_queue.cpp'
2--- src/server/compositor/buffer_queue.cpp 2014-04-29 19:29:53 +0000
3+++ src/server/compositor/buffer_queue.cpp 2014-05-06 01:54:21 +0000
4@@ -129,17 +129,11 @@
5 free_buffers.push_back(current_compositor_buffer);
6 }
7
8-void mc::BufferQueue::client_acquire(std::function<void(graphics::Buffer* buffer)> complete)
9+void mc::BufferQueue::client_acquire(mc::BufferQueue::Callback complete)
10 {
11 std::unique_lock<decltype(guard)> lock(guard);
12
13- if (give_to_client)
14- {
15- BOOST_THROW_EXCEPTION(
16- std::logic_error("unexpected acquire: there is a pending completion"));
17- }
18-
19- give_to_client = std::move(complete);
20+ pending_client_notifications.push_back(std::move(complete));
21
22 if (!free_buffers.empty())
23 {
24@@ -284,7 +278,8 @@
25 void mc::BufferQueue::force_requests_to_complete()
26 {
27 std::unique_lock<std::mutex> lock(guard);
28- if (give_to_client && !ready_to_composite_queue.empty())
29+ if (!pending_client_notifications.empty() &&
30+ !ready_to_composite_queue.empty())
31 {
32 auto const buffer = pop(ready_to_composite_queue);
33 while (!ready_to_composite_queue.empty())
34@@ -317,7 +312,8 @@
35 std::unique_lock<std::mutex> lock)
36 {
37 /* Clears callback */
38- auto give_to_client_cb = std::move(give_to_client);
39+ auto give_to_client_cb = std::move(pending_client_notifications.front());
40+ pending_client_notifications.pop_front();
41
42 bool const resize_buffer = buffer->size() != the_properties.size;
43 if (resize_buffer)
44@@ -381,7 +377,7 @@
45 mg::Buffer* buffer,
46 std::unique_lock<std::mutex> lock)
47 {
48- if (give_to_client)
49+ if (!pending_client_notifications.empty())
50 give_buffer_to_client(buffer, std::move(lock));
51 else
52 free_buffers.push_back(buffer);
53
54=== modified file 'src/server/compositor/buffer_queue.h'
55--- src/server/compositor/buffer_queue.h 2014-04-29 19:29:53 +0000
56+++ src/server/compositor/buffer_queue.h 2014-05-06 01:54:21 +0000
57@@ -38,11 +38,13 @@
58 class BufferQueue : public BufferBundle
59 {
60 public:
61+ typedef std::function<void(graphics::Buffer* buffer)> Callback;
62+
63 BufferQueue(int nbuffers,
64 std::shared_ptr<graphics::GraphicBufferAllocator> const& alloc,
65 graphics::BufferProperties const& props);
66
67- void client_acquire(std::function<void(graphics::Buffer* buffer)> complete) override;
68+ void client_acquire(Callback complete) override;
69 void client_release(graphics::Buffer* buffer) override;
70 std::shared_ptr<graphics::Buffer> compositor_acquire(void const* user_id) override;
71 void compositor_release(std::shared_ptr<graphics::Buffer> const& buffer) override;
72@@ -75,7 +77,7 @@
73 std::vector<void const*> current_buffer_users;
74 graphics::Buffer* current_compositor_buffer;
75
76- std::function<void(graphics::Buffer* buffer)> give_to_client;
77+ std::deque<Callback> pending_client_notifications;
78
79 int nbuffers;
80 bool frame_dropping_enabled;
81
82=== modified file 'tests/unit-tests/compositor/test_buffer_queue.cpp'
83--- tests/unit-tests/compositor/test_buffer_queue.cpp 2014-05-05 21:50:59 +0000
84+++ tests/unit-tests/compositor/test_buffer_queue.cpp 2014-05-06 01:54:21 +0000
85@@ -289,29 +289,34 @@
86 }
87 }
88
89-TEST_F(BufferQueueTest, throws_if_client_acquire_has_pending_completion)
90+/* Regression test for LP: #1315302 */
91+TEST_F(BufferQueueTest, clients_can_have_multiple_pending_completions)
92 {
93- mc::BufferQueue q(2, allocator, basic_properties);
94- ASSERT_THAT(q.framedropping_allowed(), Eq(false));
95-
96- auto handle = client_acquire_async(q);
97- ASSERT_THAT(handle->has_acquired_buffer(), Eq(true));
98-
99- handle->release_buffer();
100-
101- auto fail_if_called = [&](mg::Buffer* client_buffer)
102+ int const nbuffers = 3;
103+ mc::BufferQueue q(nbuffers, allocator, basic_properties);
104+
105+ for (int i = 0; i < nbuffers - 1; ++i)
106 {
107- q.client_release(client_buffer);
108- FAIL();
109- };
110-
111- /* All buffers have been exhausted,
112- * hence the callback should not be invoked
113- */
114- q.client_acquire(fail_if_called);
115-
116- /* Now there is a pending completion */
117- EXPECT_THROW(q.client_acquire(fail_if_called), std::logic_error);
118+ auto handle = client_acquire_async(q);
119+ ASSERT_THAT(handle->has_acquired_buffer(), Eq(true));
120+ handle->release_buffer();
121+ }
122+
123+ auto handle1 = client_acquire_async(q);
124+ ASSERT_THAT(handle1->has_acquired_buffer(), Eq(false));
125+
126+ auto handle2 = client_acquire_async(q);
127+ ASSERT_THAT(handle1->has_acquired_buffer(), Eq(false));
128+
129+ for (int i = 0; i < nbuffers + 1; ++i)
130+ q.compositor_release(q.compositor_acquire(this));
131+
132+ EXPECT_THAT(handle1->has_acquired_buffer(), Eq(true));
133+ EXPECT_THAT(handle2->has_acquired_buffer(), Eq(true));
134+ EXPECT_THAT(handle1->buffer(), Ne(handle2->buffer()));
135+
136+ handle1->release_buffer();
137+ handle2->release_buffer();
138 }
139
140 TEST_F(BufferQueueTest, compositor_acquires_frames_in_order_for_synchronous_client)

Subscribers

People subscribed via source and target branches