Mir

Merge lp:~vanvugt/mir/optional-callbacks into lp:~mir-team/mir/trunk

Proposed by Daniel van Vugt
Status: Rejected
Rejected by: Alan Griffiths
Proposed branch: lp:~vanvugt/mir/optional-callbacks
Merge into: lp:~mir-team/mir/trunk
Diff against target: 999 lines (+236/-200)
21 files modified
examples/demo_client.c (+1/-6)
examples/demo_client_accelerated.cpp (+1/-7)
examples/demo_client_unaccelerated.c (+1/-7)
examples/eglapp.c (+1/-3)
include/mir_toolkit/mir_client_library.h (+19/-13)
include/mir_toolkit/mir_client_library_lightdm.h (+1/-2)
src/client/mir_client_library.cpp (+20/-7)
src/client/mir_connection.cpp (+8/-8)
src/client/mir_connection.h (+3/-5)
src/client/mir_wait_handle.cpp (+24/-0)
src/client/mir_wait_handle.h (+6/-0)
tests/acceptance-tests/test_client_library.cpp (+50/-14)
tests/acceptance-tests/test_focus_management_api.cpp (+2/-10)
tests/acceptance-tests/test_surfaceloop.cpp (+6/-31)
tests/integration-tests/test_display_info.cpp (+1/-7)
tests/integration-tests/test_drm_auth_magic.cpp (+2/-8)
tests/integration-tests/test_error_reporting.cpp (+2/-25)
tests/integration-tests/test_surfaceloop.cpp (+8/-34)
tests/unit-tests/client/test_client_mir_surface.cpp (+1/-5)
tests/unit-tests/client/test_mir_connection.cpp (+4/-8)
tests/unit-tests/client/test_wait_handle.cpp (+75/-0)
To merge this branch: bzr merge lp:~vanvugt/mir/optional-callbacks
Reviewer Review Type Date Requested Status
Chris Halse Rogers Approve
Alan Griffiths Disapprove
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+153049@code.launchpad.net

This proposal supersedes a proposal from 2013-03-12.

Commit message

Demonstrate how to make callbacks optional to the client API. Starting with
mir_connect() only. Callbacks are optionally attached to a MirWaitHandle.
This simplifies most client use-cases so you will see a lot of logic is
removed.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Kevin DuBois (kdub) wrote : Posted in a previous version of this proposal

my initial reaction is that I like the idea of optional callbacks. Seeing as this is a change to the client api though, I'll mark as 'needs info' until we get more opinions on the matter in

review: Needs Information
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal

PASSED: Continuous integration, rev:418
http://jenkins.qa.ubuntu.com/job/mir-ci/20/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-quantal-amd64-ci/20//console

Click here to trigger a rebuild:
http://jenkins.qa.ubuntu.com/job/mir-ci/20//rebuild/?

review: Approve (continuous-integration)
Revision history for this message
Robert Ancell (robert-ancell) wrote : Posted in a previous version of this proposal

I think register_callback is a bit misleading - as you can have only one callback set_callback seems more appropriate.

Is both context and callback_owner required? This seems redundant.

I don't like the use of void pointers in the callbacks, that is a step backwards from having a typed callback in the client functions.

Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Yeah I agree about set_callback. Not sure what I was thinking at the time. register_... sounds clumsy.

Yes context and owner are required to support the existing callbacks (client demos) without modification. But we could modify the clients to support single parameter callbacks.

Yeah I know there's a type safety issue with void* and have two proposals for fixing it:
  (1) Remove "owner" as mentioned above. Then "context" is opaque to Mir and is never cast; or
  (2) https://code.launchpad.net/~vanvugt/mir/simple-connect/+merge/147305

Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Ok, "register" has been changed to "set".

I am willing to remove "owner" to improve type strength, but would want confirmation that people agree, before I invest the effort to modify all the clients and tests' callbacks.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal

PASSED: Continuous integration, rev:420
http://jenkins.qa.ubuntu.com/job/mir-ci/50/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-quantal-amd64-ci/51//console

Click here to trigger a rebuild:
http://jenkins.qa.ubuntu.com/job/mir-ci/50//rebuild/?

review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal

PASSED: Continuous integration, rev:420
http://jenkins.qa.ubuntu.com/job/mir-ci/52/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-quantal-amd64-ci/53//console

Click here to trigger a rebuild:
http://jenkins.qa.ubuntu.com/job/mir-ci/52//rebuild/?

review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal

PASSED: Continuous integration, rev:422
http://jenkins.qa.ubuntu.com/job/mir-ci/65/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-quantal-amd64-ci/66//console

Click here to trigger a rebuild:
http://jenkins.qa.ubuntu.com/job/mir-ci/65//rebuild/?

review: Approve (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Proposed yet again. The currently open question is: Do people want me to convert the generic callbacks to single parameters in order to remove the type safety issue (hence remove "void *owner")?

Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Actually, that might be a silly question. Removing the owner feature (self parameter of generic_callback) looks like a bad idea. I'd have to add significant logic (or significant casting assumptions) to get the result of an async call (e.g. MirConnection*). Not recommended.

Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Wait, no. It is possible to do cleanly. I'll do it today.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

PASSED: Continuous integration, rev:423
http://jenkins.qa.ubuntu.com/job/mir-ci/66/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-quantal-amd64-ci/67//console

Click here to trigger a rebuild:
http://jenkins.qa.ubuntu.com/job/mir-ci/66//rebuild/?

review: Approve (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

The discussions leading to the current design indicated that the principle use-case was that a callback would be supplied and the wait handle could (and usually would) be ignored.

The wait handles are a convenience for code that didn't manage its won synchronization - this proposal makes them a fundamental part of the callback based use-case.

There are definitely inelegances in the current API, but this complicates the principle use case.

review: Disapprove
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

You will see the "principle use case" is actually not used once as yet. We only actually need callbacks right now in test cases to verify they work.

So the "principle use case" has come from hearsay requirements from people who actually aren't even using Mir yet. Once they do, they are very likely to discover the approach proposed here is preferable.

Revision history for this message
Chris Halse Rogers (raof) wrote :

This approach makes callback-based code slightly more annoying - it becomes

mir_callback_on(mir_connect(socket, name, &connection), callback, ctx);

rather than

mir_connect(socket, name, callback, ctx);

In return for this, it makes non-callback-based code - which is *everything* we've written so far - XMir, the Mesa EGL platform, all our demos - *significantly* less annoying.

It's not the API that I'd like, but it's a significant improvement on what we currently have.

As we don't have consensus on a better API, I'm willing to approve this on the basis that it'd be an acceptable compromise if we don't reach a different consensus.

review: Approve
Revision history for this message
Chris Halse Rogers (raof) wrote :

To the mailing list!

Unmerged revisions

423. By Daniel van Vugt

Simplified, and removed the type safety problem.

422. By Daniel van Vugt

Fix conflict (build failure) introduced by upstream changes.

421. By Daniel van Vugt

Merge latest lp:mir

420. By Daniel van Vugt

Clean up: "register_callback" --> "set_callback"

419. By Daniel van Vugt

Merge latest lp:mir

418. By Daniel van Vugt

Merge test_wait.cpp into test_wait_handle.cpp

417. By Daniel van Vugt

Fix conflicts and merge problems with upstream changes.

416. By Daniel van Vugt

Merge latest lp:mir

415. By Daniel van Vugt

Shrink the diff a little.

414. By Daniel van Vugt

Merge latest lp:mir and fix numerous conflicts with mir_toolkit changes.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'examples/demo_client.c'
2--- examples/demo_client.c 2013-03-07 08:04:05 +0000
3+++ examples/demo_client.c 2013-03-13 03:34:24 +0000
4@@ -48,11 +48,6 @@
5 /// needs to be accessible both to callbacks and to the control function.
6 /// \snippet demo_client.c Callback_tag
7 ///\internal [Callback_tag]
8-// Callback to update MirDemoState on connection
9-static void connection_callback(MirConnection *new_connection, void *context)
10-{
11- ((MirDemoState*)context)->connection = new_connection;
12-}
13
14 // Callback to update MirDemoState on surface_create
15 static void surface_create_callback(MirSurface *new_surface, void *context)
16@@ -93,7 +88,7 @@
17 /// \snippet demo_client.c connect_tag
18 ///\internal [connect_tag]
19 // Call mir_connect and wait for callback to complete.
20- mir_wait_for(mir_connect(server, __PRETTY_FUNCTION__, connection_callback, &mcd));
21+ mir_wait_for(mir_connect(server, __PRETTY_FUNCTION__, &mcd.connection));
22 puts("Connected");
23 ///\internal [connect_tag]
24
25
26=== modified file 'examples/demo_client_accelerated.cpp'
27--- examples/demo_client_accelerated.cpp 2013-03-07 08:04:05 +0000
28+++ examples/demo_client_accelerated.cpp 2013-03-13 03:34:24 +0000
29@@ -32,12 +32,6 @@
30 static MirConnection *connection = 0;
31 static MirSurface *surface = 0;
32
33-static void set_connection(MirConnection *new_connection, void * context)
34-{
35- (void)context;
36- connection = new_connection;
37-}
38-
39 static void surface_create_callback(MirSurface *new_surface, void *context)
40 {
41 (void)context;
42@@ -76,7 +70,7 @@
43
44 puts("Starting");
45
46- mir_wait_for(mir_connect(socket_file, __PRETTY_FUNCTION__, set_connection, 0));
47+ mir_wait_for(mir_connect(socket_file, __PRETTY_FUNCTION__, &connection));
48 puts("Connected");
49
50 assert(connection != NULL);
51
52=== modified file 'examples/demo_client_unaccelerated.c'
53--- examples/demo_client_unaccelerated.c 2013-03-07 08:04:05 +0000
54+++ examples/demo_client_unaccelerated.c 2013-03-13 03:34:24 +0000
55@@ -30,12 +30,6 @@
56 static MirConnection *connection = 0;
57 static MirSurface *surface = 0;
58
59-static void set_connection(MirConnection *new_connection, void * context)
60-{
61- (void)context;
62- connection = new_connection;
63-}
64-
65 static void surface_create_callback(MirSurface *new_surface, void *context)
66 {
67 (void)context;
68@@ -136,7 +130,7 @@
69
70 puts("Starting");
71
72- mir_wait_for(mir_connect(socket_file, __PRETTY_FUNCTION__, set_connection, 0));
73+ mir_wait_for(mir_connect(socket_file, __PRETTY_FUNCTION__, &connection));
74 puts("Connected");
75
76 assert(connection != NULL);
77
78=== modified file 'examples/eglapp.c'
79--- examples/eglapp.c 2013-03-12 03:59:45 +0000
80+++ examples/eglapp.c 2013-03-13 03:34:24 +0000
81@@ -118,9 +118,7 @@
82 EGLContext eglctx;
83 EGLBoolean ok;
84
85- mir_wait_for(mir_connect(servername, appname,
86- (mir_connected_callback)assign_result,
87- &connection));
88+ mir_wait_for(mir_connect(servername, appname, &connection));
89 CHECK(mir_connection_is_valid(connection), "Can't get connection");
90
91 mir_connection_get_display_info(connection, &dinfo);
92
93=== modified file 'include/mir_toolkit/mir_client_library.h'
94--- include/mir_toolkit/mir_client_library.h 2013-03-07 08:04:05 +0000
95+++ include/mir_toolkit/mir_client_library.h 2013-03-13 03:34:24 +0000
96@@ -41,12 +41,10 @@
97 typedef struct MirWaitHandle MirWaitHandle;
98
99 /**
100- * Callback to be passed when issuing a mir_connect request.
101- * \param [in] connection the new connection
102- * \param [in,out] client_context context provided by client in calling
103- * mir_connect
104+ * A generic callback that can be used with mir_callback_on().
105+ * \param [in] context Context data for this callback.
106 */
107-typedef void (*mir_connected_callback)(MirConnection *connection, void *client_context);
108+typedef void (*mir_generic_callback)(void *context);
109
110 /**
111 * Callback to be passed when calling:
112@@ -147,18 +145,15 @@
113 * Request a connection to the MIR server. The supplied callback is
114 * called when the connection is established, or fails. The returned
115 * wait handle remains valid until the connection has been released.
116- * \param [in] server a name identifying the server
117- * \param [in] app_name a name referring to the application
118- * \param [in] callback callback function to be invoked when request
119- * completes
120- * \param [in,out] client_context passed to the callback function
121- * \return a handle that can be passed to mir_wait_for
122+ * \param [in] server a name identifying the server
123+ * \param [in] app_name a name referring to the application
124+ * \param [out] result where to store the connection handle on completion
125+ * \return a handle that can be passed to mir_wait_for
126 */
127 MirWaitHandle *mir_connect(
128 char const *server,
129 char const *app_name,
130- mir_connected_callback callback,
131- void *client_context);
132+ MirConnection **result);
133
134 /**
135 * Test for a valid connection
136@@ -316,6 +311,17 @@
137 void mir_wait_for(MirWaitHandle *wait_handle);
138
139 /**
140+ * Register a callback to be called when the specified wait handle is
141+ * completed.
142+ * \param [in] wait The wait handle to callback on.
143+ * \param [in] cb The callback to call when 'wait' is signaled.
144+ * \param [in] context Extra data to pass to the callback.
145+ */
146+void mir_callback_on(MirWaitHandle *wait,
147+ mir_generic_callback cb,
148+ void *context);
149+
150+/**
151 * Return the id of the surface. (Only useful for debug output.)
152 * \param [in] surface the surface
153 * \return an internal id that identifies the surfaceS
154
155=== modified file 'include/mir_toolkit/mir_client_library_lightdm.h'
156--- include/mir_toolkit/mir_client_library_lightdm.h 2013-03-07 08:04:05 +0000
157+++ include/mir_toolkit/mir_client_library_lightdm.h 2013-03-13 03:34:24 +0000
158@@ -41,8 +41,7 @@
159 char const *server,
160 int lightdm_id,
161 char const *app_name,
162- mir_connected_callback callback,
163- void *client_context);
164+ MirConnection **result);
165
166
167 /**
168
169=== modified file 'src/client/mir_client_library.cpp'
170--- src/client/mir_client_library.cpp 2013-03-07 08:04:05 +0000
171+++ src/client/mir_client_library.cpp 2013-03-13 03:34:24 +0000
172@@ -44,7 +44,7 @@
173 mir_toolkit::MirConnection error_connection;
174 }
175
176-mir_toolkit::MirWaitHandle* mir_toolkit::mir_connect(char const* socket_file, char const* name, mir_connected_callback callback, void * context)
177+mir_toolkit::MirWaitHandle* mir_toolkit::mir_connect(char const* socket_file, char const* name, MirConnection **result)
178 {
179
180 try
181@@ -57,12 +57,17 @@
182 log,
183 client_platform_factory);
184
185- return connection->connect(name, callback, context);
186+ return connection->connect(name, result);
187 }
188 catch (std::exception const& x)
189 {
190 error_connection.set_error_message(x.what());
191- callback(&error_connection, context);
192+
193+ // Test cases expect a non-null error connection but why not null
194+ // for simpler error handling?
195+ if (result)
196+ *result = &error_connection;
197+
198 return 0;
199 }
200 }
201@@ -180,6 +185,14 @@
202 wait_handle->wait_for_result();
203 }
204
205+void mir_toolkit::mir_callback_on(MirWaitHandle *wait,
206+ mir_generic_callback cb,
207+ void *context)
208+{
209+ if (wait)
210+ wait->set_callback(cb, context);
211+}
212+
213 mir_toolkit::MirEGLNativeWindowType mir_toolkit::mir_surface_get_egl_native_window(MirSurface *surface)
214 {
215 return surface->generate_native_window();
216@@ -197,8 +210,7 @@
217 char const *server,
218 int lightdm_id,
219 char const *app_name,
220- mir_connected_callback callback,
221- void *client_context)
222+ MirConnection **result)
223 try
224 {
225 auto log = std::make_shared<mcl::ConsoleLogger>();
226@@ -209,12 +221,13 @@
227 log,
228 client_platform_factory);
229
230- return connection->connect(lightdm_id, app_name, callback, client_context);
231+ return connection->connect(lightdm_id, app_name, result);
232 }
233 catch (std::exception const& x)
234 {
235 error_connection.set_error_message(x.what());
236- callback(&error_connection, client_context);
237+ if (result)
238+ *result = 0;
239 return 0;
240 }
241
242
243=== modified file 'src/client/mir_connection.cpp'
244--- src/client/mir_connection.cpp 2013-03-07 08:04:05 +0000
245+++ src/client/mir_connection.cpp 2013-03-13 03:34:24 +0000
246@@ -126,7 +126,7 @@
247 return new_wait_handle;
248 }
249
250-void mir_toolkit::MirConnection::connected(mir_connected_callback callback, void * context)
251+void mir_toolkit::MirConnection::connected(MirConnection **result)
252 {
253 /*
254 * We need to create the client platform after the connection has been
255@@ -136,14 +136,15 @@
256 platform = client_platform_factory->create_client_platform(this);
257 native_display = platform->create_egl_native_display();
258
259- callback(this, context);
260+ if (result)
261+ *result = this;
262+
263 connect_wait_handle.result_received();
264 }
265
266 mir_toolkit::MirWaitHandle* mir_toolkit::MirConnection::connect(
267 const char* app_name,
268- mir_connected_callback callback,
269- void * context)
270+ MirConnection **result)
271 {
272 connect_parameters.set_application_name(app_name);
273 server.connect(
274@@ -151,15 +152,14 @@
275 &connect_parameters,
276 &connect_result,
277 google::protobuf::NewCallback(
278- this, &MirConnection::connected, callback, context));
279+ this, &MirConnection::connected, result));
280 return &connect_wait_handle;
281 }
282
283 mir_toolkit::MirWaitHandle* mir_toolkit::MirConnection::connect(
284 int lightdm_id,
285 const char* app_name,
286- mir_connected_callback callback,
287- void * context)
288+ MirConnection **result)
289 {
290 connect_parameters.set_application_name(app_name);
291 connect_parameters.set_lightdm_id(lightdm_id);
292@@ -168,7 +168,7 @@
293 &connect_parameters,
294 &connect_result,
295 google::protobuf::NewCallback(
296- this, &MirConnection::connected, callback, context));
297+ this, &MirConnection::connected, result));
298 return &connect_wait_handle;
299 }
300
301
302=== modified file 'src/client/mir_connection.h'
303--- src/client/mir_connection.h 2013-03-07 08:04:05 +0000
304+++ src/client/mir_connection.h 2013-03-13 03:34:24 +0000
305@@ -71,14 +71,12 @@
306
307 MirWaitHandle* connect(
308 const char* app_name,
309- mir_connected_callback callback,
310- void * context);
311+ MirConnection **result);
312
313 MirWaitHandle* connect(
314 int lightdm_id,
315 const char* app_name,
316- mir_connected_callback callback,
317- void * context);
318+ MirConnection **result);
319
320 void select_focus_by_lightdm_id(int lightdm_id);
321
322@@ -128,7 +126,7 @@
323 struct SurfaceRelease;
324
325 void done_disconnect();
326- void connected(mir_connected_callback callback, void * context);
327+ void connected(MirConnection **result);
328 void released(SurfaceRelease );
329 void done_drm_auth_magic(mir_drm_auth_magic_callback callback, void* context);
330 };
331
332=== modified file 'src/client/mir_wait_handle.cpp'
333--- src/client/mir_wait_handle.cpp 2013-03-08 07:20:43 +0000
334+++ src/client/mir_wait_handle.cpp 2013-03-13 03:34:24 +0000
335@@ -22,6 +22,9 @@
336 mir_toolkit::MirWaitHandle::MirWaitHandle() :
337 guard(),
338 wait_condition(),
339+ callback(nullptr),
340+ callback_arg(nullptr),
341+ called_back(false),
342 expecting(0),
343 received(0)
344 {
345@@ -42,6 +45,7 @@
346 {
347 std::unique_lock<std::mutex> lock(guard);
348
349+ called_back = false;
350 received++;
351 wait_condition.notify_all();
352 }
353@@ -53,7 +57,27 @@
354 while ((!expecting && !received) || (received < expecting))
355 wait_condition.wait(lock);
356
357+ if (!called_back && callback)
358+ {
359+ callback(callback_arg);
360+ called_back = true;
361+ }
362+
363 received = 0;
364 expecting = 0;
365 }
366
367+void mir_toolkit::MirWaitHandle::set_callback(Callback cb, void *context)
368+{
369+ std::unique_lock<std::mutex> lock(guard);
370+
371+ callback = cb;
372+ callback_arg = context;
373+ called_back = false;
374+ if (received && callback)
375+ {
376+ callback(callback_arg);
377+ called_back = true;
378+ }
379+}
380+
381
382=== modified file 'src/client/mir_wait_handle.h'
383--- src/client/mir_wait_handle.h 2013-03-08 07:20:43 +0000
384+++ src/client/mir_wait_handle.h 2013-03-13 03:34:24 +0000
385@@ -31,14 +31,20 @@
386 MirWaitHandle();
387 ~MirWaitHandle();
388
389+ typedef void (*Callback)(void *context);
390+
391 void expect_result();
392 void result_received();
393 void wait_for_result();
394+ void set_callback(Callback cb, void *context);
395
396 private:
397 std::mutex guard;
398 std::condition_variable wait_condition;
399
400+ Callback callback;
401+ void *callback_arg;
402+ bool called_back;
403 int expecting;
404 int received;
405 };
406
407=== modified file 'tests/acceptance-tests/test_client_library.cpp'
408--- tests/acceptance-tests/test_client_library.cpp 2013-03-07 08:04:05 +0000
409+++ tests/acceptance-tests/test_client_library.cpp 2013-03-13 03:34:24 +0000
410@@ -49,14 +49,15 @@
411 ClientConfigCommon()
412 : connection(0)
413 , surface(0),
414- buffers(0)
415+ buffers(0),
416+ called_back(false)
417 {
418 }
419
420- static void connection_callback(MirConnection * connection, void * context)
421+ static void connection_callback(void *context)
422 {
423 ClientConfigCommon * config = reinterpret_cast<ClientConfigCommon *>(context);
424- config->connection = connection;
425+ config->called_back = true;
426 }
427
428 static void create_surface_callback(MirSurface * surface, void * context)
429@@ -100,6 +101,7 @@
430 MirConnection* connection;
431 MirSurface* surface;
432 int buffers;
433+ bool called_back;
434 };
435 }
436
437@@ -109,10 +111,37 @@
438 {
439 void exec()
440 {
441- mir_wait_for(mir_connect(mir_test_socket, __PRETTY_FUNCTION__, connection_callback, this));
442-
443- ASSERT_TRUE(connection != NULL);
444- EXPECT_TRUE(mir_connection_is_valid(connection));
445+ mir_wait_for(mir_connect(mir_test_socket, __PRETTY_FUNCTION__,
446+ &connection));
447+
448+ ASSERT_TRUE(connection != NULL);
449+ EXPECT_TRUE(mir_connection_is_valid(connection));
450+ EXPECT_STREQ(mir_connection_get_error_message(connection), "");
451+
452+ mir_connection_release(connection);
453+ }
454+ } client_config;
455+
456+ launch_client_process(client_config);
457+}
458+
459+TEST_F(DefaultDisplayServerTestFixture, connect_calls_back)
460+{
461+ struct ClientConfig : ClientConfigCommon
462+ {
463+ void exec()
464+ {
465+ called_back = false;
466+
467+ MirWaitHandle *wait = mir_connect(mir_test_socket,
468+ __PRETTY_FUNCTION__,
469+ &connection);
470+ mir_callback_on(wait, connection_callback, this);
471+ mir_wait_for(wait);
472+
473+ ASSERT_TRUE(connection != NULL);
474+ EXPECT_TRUE(mir_connection_is_valid(connection));
475+ EXPECT_TRUE(called_back);
476 EXPECT_STREQ(mir_connection_get_error_message(connection), "");
477
478 mir_connection_release(connection);
479@@ -129,7 +158,8 @@
480 void exec()
481 {
482
483- mir_wait_for(mir_connect(mir_test_socket, __PRETTY_FUNCTION__, connection_callback, this));
484+ mir_wait_for(mir_connect(mir_test_socket, __PRETTY_FUNCTION__,
485+ &connection));
486
487 ASSERT_TRUE(connection != NULL);
488 EXPECT_TRUE(mir_connection_is_valid(connection));
489@@ -200,7 +230,8 @@
490
491 void exec()
492 {
493- mir_wait_for(mir_connect(mir_test_socket, __PRETTY_FUNCTION__, connection_callback, this));
494+ mir_wait_for(mir_connect(mir_test_socket, __PRETTY_FUNCTION__,
495+ &connection));
496
497 ASSERT_TRUE(connection != NULL);
498 EXPECT_TRUE(mir_connection_is_valid(connection));
499@@ -252,7 +283,8 @@
500 void exec()
501 {
502
503- mir_wait_for(mir_connect(mir_test_socket, __PRETTY_FUNCTION__, connection_callback, this));
504+ mir_wait_for(mir_connect(mir_test_socket, __PRETTY_FUNCTION__,
505+ &connection));
506
507 ASSERT_TRUE(connection != NULL);
508 EXPECT_TRUE(mir_connection_is_valid(connection));
509@@ -288,7 +320,8 @@
510 {
511 void exec()
512 {
513- mir_wait_for(mir_connect(mir_test_socket, __PRETTY_FUNCTION__, connection_callback, this));
514+ mir_wait_for(mir_connect(mir_test_socket, __PRETTY_FUNCTION__,
515+ &connection));
516 ASSERT_TRUE(connection != NULL);
517
518 MirPlatformPackage platform_package;
519@@ -314,7 +347,8 @@
520 {
521 void exec()
522 {
523- mir_wait_for(mir_connect(mir_test_socket, __PRETTY_FUNCTION__, connection_callback, this));
524+ mir_wait_for(mir_connect(mir_test_socket, __PRETTY_FUNCTION__,
525+ &connection));
526 ASSERT_TRUE(connection != NULL);
527
528 MirDisplayInfo display_info;
529@@ -338,7 +372,8 @@
530 {
531 void exec()
532 {
533- mir_wait_for(mir_connect("garbage", __PRETTY_FUNCTION__, connection_callback, this));
534+ mir_wait_for(mir_connect("garbage", __PRETTY_FUNCTION__,
535+ &connection));
536 ASSERT_TRUE(connection != NULL);
537
538 char const* error = mir_connection_get_error_message(connection);
539@@ -360,7 +395,8 @@
540 {
541 void exec()
542 {
543- mir_wait_for(mir_connect("garbage", __PRETTY_FUNCTION__, connection_callback, this));
544+ mir_wait_for(mir_connect("garbage", __PRETTY_FUNCTION__,
545+ &connection));
546
547 MirSurfaceParameters const request_params =
548 {
549
550=== modified file 'tests/acceptance-tests/test_focus_management_api.cpp'
551--- tests/acceptance-tests/test_focus_management_api.cpp 2013-03-07 08:04:05 +0000
552+++ tests/acceptance-tests/test_focus_management_api.cpp 2013-03-13 03:34:24 +0000
553@@ -56,12 +56,6 @@
554 {
555 }
556
557- static void connection_callback(MirConnection* connection, void* context)
558- {
559- ClientConfigCommon* config = reinterpret_cast<ClientConfigCommon *>(context);
560- config->connection = connection;
561- }
562-
563 static void create_surface_callback(MirSurface* surface, void* context)
564 {
565 ClientConfigCommon* config = reinterpret_cast<ClientConfigCommon *>(context);
566@@ -200,8 +194,7 @@
567 mir_test_socket,
568 lightdm_id,
569 __PRETTY_FUNCTION__,
570- connection_callback,
571- this));
572+ &connection));
573
574 ASSERT_TRUE(connection != NULL);
575
576@@ -229,8 +222,7 @@
577 mir_wait_for(mir_connect(
578 mir_test_socket,
579 __PRETTY_FUNCTION__,
580- connection_callback,
581- this));
582+ &connection));
583
584 wait_for(focus_ready);
585 mir_select_focus_by_lightdm_id(connection, lightdm_id);
586
587=== modified file 'tests/acceptance-tests/test_surfaceloop.cpp'
588--- tests/acceptance-tests/test_surfaceloop.cpp 2013-03-07 08:04:05 +0000
589+++ tests/acceptance-tests/test_surfaceloop.cpp 2013-03-13 03:34:24 +0000
590@@ -96,28 +96,6 @@
591 {
592 }
593
594- static void connection_callback(MirConnection * connection, void * context)
595- {
596- ClientConfigCommon * config = reinterpret_cast<ClientConfigCommon *>(context);
597- config->connected(connection);
598- }
599-
600- void connected(MirConnection * new_connection)
601- {
602- std::unique_lock<std::mutex> lock(guard);
603- connection = new_connection;
604- wait_condition.notify_all();
605- }
606-
607- void wait_for_connect()
608- {
609- std::unique_lock<std::mutex> lock(guard);
610- while (!connection)
611- wait_condition.wait(lock);
612- }
613-
614- std::mutex guard;
615- std::condition_variable wait_condition;
616 MirConnection * connection;
617 static const int max_surface_count = 5;
618 SurfaceSync ssync[max_surface_count];
619@@ -160,9 +138,8 @@
620 {
621 void exec()
622 {
623- mir_connect(mir_test_socket, __PRETTY_FUNCTION__, connection_callback, this);
624-
625- wait_for_connect();
626+ mir_wait_for(mir_connect(mir_test_socket, __PRETTY_FUNCTION__,
627+ &connection));
628
629 MirSurfaceParameters request_params =
630 {
631@@ -213,9 +190,8 @@
632 {
633 void exec()
634 {
635- mir_connect(mir_test_socket, __PRETTY_FUNCTION__, connection_callback, this);
636-
637- wait_for_connect();
638+ mir_wait_for(mir_connect(mir_test_socket, __PRETTY_FUNCTION__,
639+ &connection));
640
641 MirSurfaceParameters request_params =
642 {
643@@ -257,9 +233,8 @@
644 {
645 void exec()
646 {
647- mir_connect(mir_test_socket, __PRETTY_FUNCTION__, connection_callback, this);
648-
649- wait_for_connect();
650+ mir_wait_for(mir_connect(mir_test_socket, __PRETTY_FUNCTION__,
651+ &connection));
652
653 MirSurfaceParameters request_params =
654 {
655
656=== modified file 'tests/integration-tests/test_display_info.cpp'
657--- tests/integration-tests/test_display_info.cpp 2013-03-07 08:04:05 +0000
658+++ tests/integration-tests/test_display_info.cpp 2013-03-13 03:34:24 +0000
659@@ -106,12 +106,6 @@
660
661 };
662
663-void connection_callback(MirConnection* connection, void* context)
664-{
665- auto connection_ptr = static_cast<MirConnection**>(context);
666- *connection_ptr = connection;
667-}
668-
669 }
670
671 TEST_F(BespokeDisplayServerTestFixture, display_info_reaches_client)
672@@ -139,7 +133,7 @@
673 {
674 MirConnection* connection{nullptr};
675 mir_wait_for(mir_connect(mir_test_socket, __PRETTY_FUNCTION__,
676- connection_callback, &connection));
677+ &connection));
678
679 MirDisplayInfo info;
680
681
682=== modified file 'tests/integration-tests/test_drm_auth_magic.cpp'
683--- tests/integration-tests/test_drm_auth_magic.cpp 2013-03-07 08:04:05 +0000
684+++ tests/integration-tests/test_drm_auth_magic.cpp 2013-03-13 03:34:24 +0000
685@@ -83,12 +83,6 @@
686 MOCK_METHOD1(drm_auth_magic, void(unsigned int));
687 };
688
689-void connection_callback(MirConnection* connection, void* context)
690-{
691- auto connection_ptr = static_cast<MirConnection**>(context);
692- *connection_ptr = connection;
693-}
694-
695 void drm_auth_magic_callback(int status, void* client_context)
696 {
697 auto status_ptr = static_cast<int*>(client_context);
698@@ -127,7 +121,7 @@
699 {
700 MirConnection* connection{nullptr};
701 mir_wait_for(mir_connect(mir_test_socket, __PRETTY_FUNCTION__,
702- connection_callback, &connection));
703+ &connection));
704
705 int const no_error{0};
706 int status{67};
707@@ -176,7 +170,7 @@
708 {
709 MirConnection* connection{nullptr};
710 mir_wait_for(mir_connect(mir_test_socket, __PRETTY_FUNCTION__,
711- connection_callback, &connection));
712+ &connection));
713
714 int status{67};
715
716
717=== modified file 'tests/integration-tests/test_error_reporting.cpp'
718--- tests/integration-tests/test_error_reporting.cpp 2013-03-07 08:04:05 +0000
719+++ tests/integration-tests/test_error_reporting.cpp 2013-03-13 03:34:24 +0000
720@@ -151,28 +151,6 @@
721 {
722 }
723
724- static void connection_callback(MirConnection * connection, void * context)
725- {
726- ClientConfigCommon * config = reinterpret_cast<ClientConfigCommon *>(context);
727- config->connected(connection);
728- }
729-
730- void connected(MirConnection * new_connection)
731- {
732- std::unique_lock<std::mutex> lock(guard);
733- connection = new_connection;
734- wait_condition.notify_all();
735- }
736-
737- void wait_for_connect()
738- {
739- std::unique_lock<std::mutex> lock(guard);
740- while (!connection)
741- wait_condition.wait(lock);
742- }
743-
744- std::mutex guard;
745- std::condition_variable wait_condition;
746 MirConnection * connection;
747 static const int max_surface_count = 5;
748 SurfaceSync ssync[max_surface_count];
749@@ -255,9 +233,8 @@
750 {
751 void exec()
752 {
753- mir_connect(mir_test_socket, __PRETTY_FUNCTION__, connection_callback, this);
754-
755- wait_for_connect();
756+ mir_wait_for(mir_connect(mir_test_socket, __PRETTY_FUNCTION__,
757+ &connection));
758
759 ASSERT_TRUE(connection != NULL);
760 EXPECT_FALSE(mir_connection_is_valid(connection));
761
762=== modified file 'tests/integration-tests/test_surfaceloop.cpp'
763--- tests/integration-tests/test_surfaceloop.cpp 2013-03-07 08:04:05 +0000
764+++ tests/integration-tests/test_surfaceloop.cpp 2013-03-13 03:34:24 +0000
765@@ -183,28 +183,6 @@
766 {
767 }
768
769- static void connection_callback(MirConnection * connection, void * context)
770- {
771- ClientConfigCommon * config = reinterpret_cast<ClientConfigCommon *>(context);
772- config->connected(connection);
773- }
774-
775- void connected(MirConnection * new_connection)
776- {
777- std::unique_lock<std::mutex> lock(guard);
778- connection = new_connection;
779- wait_condition.notify_all();
780- }
781-
782- void wait_for_connect()
783- {
784- std::unique_lock<std::mutex> lock(guard);
785- while (!connection)
786- wait_condition.wait(lock);
787- }
788-
789- std::mutex guard;
790- std::condition_variable wait_condition;
791 MirConnection * connection;
792 static const int max_surface_count = 5;
793 SurfaceSync ssync[max_surface_count];
794@@ -270,9 +248,8 @@
795 {
796 void exec()
797 {
798- mir_connect(mir_test_socket, __PRETTY_FUNCTION__, connection_callback, this);
799-
800- wait_for_connect();
801+ mir_wait_for(mir_connect(mir_test_socket, __PRETTY_FUNCTION__,
802+ &connection));
803
804 ASSERT_TRUE(connection != NULL);
805 EXPECT_TRUE(mir_connection_is_valid(connection));
806@@ -373,9 +350,8 @@
807 {
808 void exec()
809 {
810- mir_connect(mir_test_socket, __PRETTY_FUNCTION__, connection_callback, this);
811-
812- wait_for_connect();
813+ mir_wait_for(mir_connect(mir_test_socket, __PRETTY_FUNCTION__,
814+ &connection));
815
816 ASSERT_TRUE(connection != NULL);
817 EXPECT_TRUE(mir_connection_is_valid(connection));
818@@ -512,9 +488,8 @@
819 {
820 void exec()
821 {
822- mir_connect(mir_test_socket, __PRETTY_FUNCTION__, connection_callback, this);
823-
824- wait_for_connect();
825+ mir_wait_for(mir_connect(mir_test_socket, __PRETTY_FUNCTION__,
826+ &connection));
827
828 MirSurfaceParameters const request_params =
829 {
830@@ -561,9 +536,8 @@
831 {
832 void exec()
833 {
834- mir_connect(mir_test_socket, __PRETTY_FUNCTION__, connection_callback, this);
835-
836- wait_for_connect();
837+ mir_wait_for(mir_connect(mir_test_socket, __PRETTY_FUNCTION__,
838+ &connection));
839
840 MirSurfaceParameters const request_params =
841 {
842
843=== modified file 'tests/unit-tests/client/test_client_mir_surface.cpp'
844--- tests/unit-tests/client/test_client_mir_surface.cpp 2013-03-07 08:04:05 +0000
845+++ tests/unit-tests/client/test_client_mir_surface.cpp 2013-03-13 03:34:24 +0000
846@@ -201,10 +201,6 @@
847
848 namespace mt = mir::test;
849
850-void connected_callback(MirConnection* /*connection*/, void * /*client_context*/)
851-{
852-}
853-
854 struct CallBack
855 {
856 void msg() {}
857@@ -233,7 +229,7 @@
858 channel = mcl::make_rpc_channel("./test_socket_surface", logger);
859 connection = std::make_shared<MirConnection>(channel, logger, platform_factory);
860 MirWaitHandle* wait_handle = connection->connect("MirClientSurfaceTest",
861- connected_callback, 0);
862+ nullptr);
863 wait_handle->wait_for_result();
864 client_comm_channel = std::make_shared<mir::protobuf::DisplayServer::Stub>(channel.get());
865 }
866
867=== modified file 'tests/unit-tests/client/test_mir_connection.cpp'
868--- tests/unit-tests/client/test_mir_connection.cpp 2013-01-02 15:57:13 +0000
869+++ tests/unit-tests/client/test_mir_connection.cpp 2013-03-13 03:34:24 +0000
870@@ -98,10 +98,6 @@
871 std::shared_ptr<mcl::ClientPlatform> platform;
872 };
873
874-void connected_callback(MirConnection* /*connection*/, void * /*client_context*/)
875-{
876-}
877-
878 void drm_auth_magic_callback(int status, void* client_context)
879 {
880 auto status_ptr = static_cast<int*>(client_context);
881@@ -144,7 +140,7 @@
882 .WillOnce(Return(native_display));
883
884 MirWaitHandle* wait_handle = connection->connect("MirClientSurfaceTest",
885- connected_callback, 0);
886+ nullptr);
887 wait_handle->wait_for_result();
888
889 EGLNativeDisplayType connection_native_display = connection->egl_native_display();
890@@ -167,7 +163,7 @@
891 .Times(1);
892
893 MirWaitHandle* wait_handle = connection->connect("MirClientSurfaceTest",
894- connected_callback, 0);
895+ nullptr);
896 wait_handle->wait_for_result();
897
898 int const no_error{0};
899@@ -211,7 +207,7 @@
900 .WillOnce(Invoke(fill_display_info));
901
902 MirWaitHandle* wait_handle = connection->connect("MirClientSurfaceTest",
903- connected_callback, 0);
904+ nullptr);
905 wait_handle->wait_for_result();
906
907 MirDisplayInfo info;
908@@ -236,7 +232,7 @@
909 .WillOnce(Invoke(fill_display_info_100));
910
911 MirWaitHandle* wait_handle = connection->connect("MirConnectionTest",
912- connected_callback, 0);
913+ nullptr);
914 wait_handle->wait_for_result();
915
916 MirDisplayInfo info;
917
918=== modified file 'tests/unit-tests/client/test_wait_handle.cpp'
919--- tests/unit-tests/client/test_wait_handle.cpp 2013-03-07 07:19:39 +0000
920+++ tests/unit-tests/client/test_wait_handle.cpp 2013-03-13 03:34:24 +0000
921@@ -112,3 +112,78 @@
922 }
923 t.join();
924 }
925+
926+TEST(WaitHandle, no_callback)
927+{
928+ MirWaitHandle w;
929+
930+ w.result_received();
931+ EXPECT_NO_FATAL_FAILURE(w.wait_for_result());
932+}
933+
934+namespace
935+{
936+ void *cb_context = nullptr;
937+
938+ void callback(void *context)
939+ {
940+ cb_context = context;
941+ }
942+}
943+
944+TEST(WaitHandle, callback_before_signal)
945+{
946+ MirWaitHandle w;
947+ int beta, delta;
948+
949+ cb_context = 0;
950+ w.set_callback(callback, &beta);
951+ w.result_received();
952+ w.wait_for_result();
953+ EXPECT_EQ(cb_context, &beta);
954+
955+ w.result_received();
956+ w.wait_for_result();
957+ EXPECT_EQ(cb_context, &beta);
958+
959+ cb_context = 0;
960+ w.set_callback(callback, &delta);
961+ w.result_received();
962+ w.wait_for_result();
963+ EXPECT_EQ(cb_context, &delta);
964+
965+ w.set_callback(nullptr, nullptr);
966+ EXPECT_NO_FATAL_FAILURE({
967+ w.result_received();
968+ w.wait_for_result();
969+ });
970+}
971+
972+TEST(WaitHandle, callback_after_signal)
973+{
974+ MirWaitHandle w;
975+ int beta, delta;
976+
977+ cb_context = 0;
978+ w.result_received();
979+ w.set_callback(callback, &beta);
980+ w.wait_for_result();
981+ EXPECT_EQ(cb_context, &beta);
982+
983+ w.result_received();
984+ w.wait_for_result();
985+ EXPECT_EQ(cb_context, &beta);
986+
987+ cb_context = 0;
988+
989+ w.result_received();
990+ w.set_callback(callback, &delta);
991+ w.wait_for_result();
992+ EXPECT_EQ(cb_context, &delta);
993+
994+ w.set_callback(nullptr, nullptr);
995+ EXPECT_NO_FATAL_FAILURE({
996+ w.result_received();
997+ w.wait_for_result();
998+ });
999+}

Subscribers

People subscribed via source and target branches