Mir

Merge lp:~andreas-pokorny/mir/dispatchable-action-queue-and-fixes into lp:mir

Proposed by Andreas Pokorny on 2015-03-10
Status: Merged
Approved by: Andreas Pokorny on 2015-03-12
Approved revision: 2380
Merged at revision: 2394
Proposed branch: lp:~andreas-pokorny/mir/dispatchable-action-queue-and-fixes
Merge into: lp:mir
Diff against target: 276 lines (+227/-0)
6 files modified
include/common/mir/dispatch/action_queue.h (+53/-0)
src/common/dispatch/CMakeLists.txt (+1/-0)
src/common/dispatch/action_queue.cpp (+87/-0)
src/common/symbols.map (+11/-0)
tests/unit-tests/dispatch/CMakeLists.txt (+1/-0)
tests/unit-tests/dispatch/test_action_queue.cpp (+74/-0)
To merge this branch: bzr merge lp:~andreas-pokorny/mir/dispatchable-action-queue-and-fixes
Reviewer Review Type Date Requested Status
Alan Griffiths Approve on 2015-03-12
Alberto Aguirre Approve on 2015-03-12
Alexandros Frantzis (community) Approve on 2015-03-12
Chris Halse Rogers Approve on 2015-03-11
Kevin DuBois (community) 2015-03-10 Approve on 2015-03-11
PS Jenkins bot continuous-integration Approve on 2015-03-11
Review via email: mp+252451@code.launchpad.net

Commit Message

Adds ActionQueue, a simple dispatchable utility

Additionally fixes a missing mir common symbol

Description of the Change

This is another split-out from the input platform work. This includes a fix for mircommons symbols.map lacking the remove_watch symbols. A minor move and a ActionQueue which is used inside the new input platform handling code and inside stub input platform.

ActionQueue is a trivial std::function queue that implements the Dispatchable interface.

To post a comment you must log in.
2378. By Andreas Pokorny on 2015-03-10

merged lp:mir

Kevin DuBois (kdub) wrote :

suggest-fixing:
165 + {
could save some brackets for the conditional

100 + if (pipe(pipefds) < 0)
should be pipe2(pipefds, O_CLOEXEC))... also if it was O_CLOEXEC | O_NONBLOCK, we could call the write() function without the lock dance in enqueue()

147 + return FdEvent::readable|FdEvent::error;
126 + if (events&FdEvent::error)
spacing

review: Needs Fixing
Chris Halse Rogers (raof) wrote :

I think we've got enough usages of pipe2 now that we should pull mir_test/pipe.h into a utility class :).

Having said that, we really should be using an eventfd for these cases where we're just signalling. (I should go back and fix up my ones, too).

In addition to the nits picked up by Kevin:

46 + virtual FdEvents relevant_events() const override;

You've got a stray “virtual” there.

147 + return FdEvent::readable|FdEvent::error;

You don't need to specify that you handle FdEvent::error, although it's harmless.

review: Needs Fixing
2379. By Andreas Pokorny on 2015-03-11

review findings addressed

2380. By Andreas Pokorny on 2015-03-11

removed mock_dispatchable as a separate file, not needed

Kevin DuBois (kdub) wrote :

lgtm

review: Approve
Chris Halse Rogers (raof) wrote :

LGTM

review: Approve
Alexandros Frantzis (afrantzis) wrote :

Looks good.

review: Approve
Alberto Aguirre (albaguirre) wrote :

LGTM

review: Approve
Alan Griffiths (alan-griffiths) wrote :

OK

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'include/common/mir/dispatch/action_queue.h'
2--- include/common/mir/dispatch/action_queue.h 1970-01-01 00:00:00 +0000
3+++ include/common/mir/dispatch/action_queue.h 2015-03-11 12:29:17 +0000
4@@ -0,0 +1,53 @@
5+/*
6+ * Copyright © 2015 Canonical Ltd.
7+ *
8+ * This program is free software: you can redistribute it and/or modify it
9+ * under the terms of the GNU Lesser General Public License version 3,
10+ * as published by the Free Software Foundation.
11+ *
12+ * This program is distributed in the hope that it will be useful,
13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+ * GNU Lesser General Public License for more details.
16+ *
17+ * You should have received a copy of the GNU Lesser General Public License
18+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
19+ *
20+ * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com>
21+ */
22+
23+#ifndef MIR_DISPATCH_ACTION_QUEUE_H_
24+#define MIR_DISPATCH_ACTION_QUEUE_H_
25+
26+#include "mir/fd.h"
27+#include "mir/dispatch/dispatchable.h"
28+
29+#include <list>
30+#include <mutex>
31+
32+namespace mir
33+{
34+namespace dispatch
35+{
36+
37+class ActionQueue : public Dispatchable
38+{
39+public:
40+ ActionQueue();
41+ Fd watch_fd() const override;
42+
43+ void enqueue(std::function<void()> const& action);
44+
45+ bool dispatch(FdEvents events) override;
46+ FdEvents relevant_events() const override;
47+private:
48+ void consume();
49+ void wake();
50+ mir::Fd event_fd;
51+ std::mutex list_lock;
52+ std::list<std::function<void()>> actions;
53+};
54+}
55+}
56+
57+#endif // MIR_DISPATCH_ACTION_QUEUE_H_
58
59=== modified file 'src/common/dispatch/CMakeLists.txt'
60--- src/common/dispatch/CMakeLists.txt 2015-02-18 05:27:28 +0000
61+++ src/common/dispatch/CMakeLists.txt 2015-03-11 12:29:17 +0000
62@@ -16,6 +16,7 @@
63
64 list(
65 APPEND MIR_COMMON_SOURCES
66+ ${CMAKE_CURRENT_SOURCE_DIR}/action_queue.cpp
67 ${CMAKE_CURRENT_SOURCE_DIR}/simple_dispatch_thread.cpp
68 ${CMAKE_CURRENT_SOURCE_DIR}/multiplexing_dispatchable.cpp
69 ${CMAKE_CURRENT_SOURCE_DIR}/utils.cpp
70
71=== added file 'src/common/dispatch/action_queue.cpp'
72--- src/common/dispatch/action_queue.cpp 1970-01-01 00:00:00 +0000
73+++ src/common/dispatch/action_queue.cpp 2015-03-11 12:29:17 +0000
74@@ -0,0 +1,87 @@
75+/*
76+ * Copyright © 2015 Canonical Ltd.
77+ *
78+ * This program is free software: you can redistribute it and/or modify it
79+ * under the terms of the GNU Lesser General Public License version 3,
80+ * as published by the Free Software Foundation.
81+ *
82+ * This program is distributed in the hope that it will be useful,
83+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
84+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
85+ * GNU Lesser General Public License for more details.
86+ *
87+ * You should have received a copy of the GNU Lesser General Public License
88+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
89+ *
90+ * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com>
91+ */
92+
93+#include "mir/dispatch/action_queue.h"
94+
95+#include <boost/throw_exception.hpp>
96+#include <sys/eventfd.h>
97+
98+mir::dispatch::ActionQueue::ActionQueue()
99+ : event_fd{eventfd(0, EFD_CLOEXEC|EFD_NONBLOCK)}
100+{
101+ if (event_fd < 0)
102+ BOOST_THROW_EXCEPTION((std::system_error{errno,
103+ std::system_category(),
104+ "Failed to create event fd for action queue"}));
105+}
106+
107+mir::Fd mir::dispatch::ActionQueue::watch_fd() const
108+{
109+ return event_fd;
110+}
111+
112+void mir::dispatch::ActionQueue::enqueue(std::function<void()> const& action)
113+{
114+ std::unique_lock<std::mutex> lock(list_lock);
115+ actions.push_back(action);
116+ wake();
117+}
118+
119+bool mir::dispatch::ActionQueue::dispatch(FdEvents events)
120+{
121+ if (events&FdEvent::error)
122+ return false;
123+
124+ std::list<std::function<void()>> actions_to_process;
125+
126+ {
127+ std::unique_lock<std::mutex> lock(list_lock);
128+ consume();
129+ std::swap(actions_to_process, actions);
130+ }
131+
132+ while(!actions_to_process.empty())
133+ {
134+ actions_to_process.front()();
135+ actions_to_process.pop_front();
136+ }
137+ return true;
138+}
139+
140+mir::dispatch::FdEvents mir::dispatch::ActionQueue::relevant_events() const
141+{
142+ return FdEvent::readable;
143+}
144+
145+void mir::dispatch::ActionQueue::consume()
146+{
147+ uint64_t num_actions;
148+ if (read(event_fd, &num_actions, sizeof num_actions) != sizeof num_actions)
149+ BOOST_THROW_EXCEPTION((std::system_error{errno,
150+ std::system_category(),
151+ "Failed to consume action queue notification"}));
152+}
153+
154+void mir::dispatch::ActionQueue::wake()
155+{
156+ uint64_t one_more{1};
157+ if (write(event_fd, &one_more, sizeof one_more) != sizeof one_more)
158+ BOOST_THROW_EXCEPTION((std::system_error{errno,
159+ std::system_category(),
160+ "Failed to wake action queue"}));
161+}
162
163=== modified file 'src/common/symbols.map'
164--- src/common/symbols.map 2015-03-05 05:47:28 +0000
165+++ src/common/symbols.map 2015-03-11 12:29:17 +0000
166@@ -235,10 +235,21 @@
167 mir::dispatch::MultiplexingDispatchable::dispatch*;
168 mir::dispatch::MultiplexingDispatchable::relevant_events*;
169 mir::dispatch::MultiplexingDispatchable::add_watch*;
170+ mir::dispatch::MultiplexingDispatchable::remove_watch*;
171
172 typeinfo?for?mir::dispatch::MultiplexingDispatchable;
173 vtable?for?mir::dispatch::MultiplexingDispatchable;
174
175+ mir::dispatch::ActionQueue::ActionQueue*;
176+ mir::dispatch::ActionQueue::?ActionQueue*;
177+ mir::dispatch::ActionQueue::watch_fd*;
178+ mir::dispatch::ActionQueue::dispatch*;
179+ mir::dispatch::ActionQueue::relevant_events*;
180+ mir::dispatch::ActionQueue::enqueue*;
181+
182+ typeinfo?for?mir::dispatch::ActionQueue;
183+ vtable?for?mir::dispatch::ActionQueue;
184+
185 mir::detail::RefCountedLibrary::operator*;
186 mir::detail::RefCountedLibrary::?RefCountedLibrary*;
187 mir::detail::RefCountedLibrary::RefCountedLibrary*;
188
189=== modified file 'tests/unit-tests/dispatch/CMakeLists.txt'
190--- tests/unit-tests/dispatch/CMakeLists.txt 2015-02-18 05:27:28 +0000
191+++ tests/unit-tests/dispatch/CMakeLists.txt 2015-03-11 12:29:17 +0000
192@@ -1,4 +1,5 @@
193 list(APPEND UNIT_TEST_SOURCES
194+ ${CMAKE_CURRENT_SOURCE_DIR}/test_action_queue.cpp
195 ${CMAKE_CURRENT_SOURCE_DIR}/test_simple_dispatch_thread.cpp
196 ${CMAKE_CURRENT_SOURCE_DIR}/test_multiplexing_dispatchable.cpp
197 ${CMAKE_CURRENT_SOURCE_DIR}/test_dispatch_utils.cpp
198
199=== added file 'tests/unit-tests/dispatch/test_action_queue.cpp'
200--- tests/unit-tests/dispatch/test_action_queue.cpp 1970-01-01 00:00:00 +0000
201+++ tests/unit-tests/dispatch/test_action_queue.cpp 2015-03-11 12:29:17 +0000
202@@ -0,0 +1,74 @@
203+/*
204+ * Copyright © 2015 Canonical Ltd.
205+ *
206+ * This program is free software: you can redistribute it and/or modify
207+ * it under the terms of the GNU General Public License version 3 as
208+ * published by the Free Software Foundation.
209+ *
210+ * This program is distributed in the hope that it will be useful,
211+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
212+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
213+ * GNU General Public License for more details.
214+ *
215+ * You should have received a copy of the GNU General Public License
216+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
217+ *
218+ * Authored by: Andreasd Pokorny <andreas.pokorny@canonical.com>
219+ */
220+
221+#include "mir/dispatch/action_queue.h"
222+
223+#include "mir_test/fd_utils.h"
224+
225+#include <gtest/gtest.h>
226+
227+namespace mt = mir::test;
228+namespace md = mir::dispatch;
229+using namespace ::testing;
230+
231+TEST(ActionQueue, watch_fd_becomes_readable_on_enqueue)
232+{
233+ md::ActionQueue queue;
234+
235+ ASSERT_FALSE(mt::fd_is_readable(queue.watch_fd()));
236+ queue.enqueue([]{});
237+ ASSERT_TRUE(mt::fd_is_readable(queue.watch_fd()));
238+}
239+
240+TEST(ActionQueue, executes_action_on_dispatch)
241+{
242+ md::ActionQueue queue;
243+
244+ auto action_exeuted = false;
245+
246+ queue.enqueue([&](){action_exeuted = true;});
247+ ASSERT_FALSE(action_exeuted);
248+ queue.dispatch(md::FdEvent::readable);
249+ ASSERT_TRUE(action_exeuted);
250+}
251+
252+TEST(ActionQueue, calls_nothing_on_error)
253+{
254+ md::ActionQueue queue;
255+
256+ auto action_exeuted = false;
257+
258+ queue.enqueue([&](){action_exeuted = true;});
259+ queue.dispatch(md::FdEvent::error);
260+ ASSERT_FALSE(action_exeuted);
261+}
262+
263+TEST(ActionQueue, executes_action_only_once)
264+{
265+ md::ActionQueue queue;
266+
267+ auto count_executed = 0;
268+
269+ queue.enqueue([&](){++count_executed;});
270+ queue.dispatch(md::FdEvent::readable);
271+ EXPECT_THROW(queue.dispatch(md::FdEvent::readable),std::system_error);
272+ EXPECT_THROW(queue.dispatch(md::FdEvent::readable),std::system_error);
273+ EXPECT_THAT(count_executed, Eq(1));
274+}
275+
276+

Subscribers

People subscribed via source and target branches