Merge lp:~vanvugt/mir/optional-callbacks into lp:~mir-team/mir/trunk
- optional-callbacks
- Merge into trunk
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 |
Related bugs: |
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.
Description of the change
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:415
http://
Executed test runs:
SUCCESS: http://
Click here to trigger a rebuild:
http://
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
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:418
http://
Executed test runs:
SUCCESS: http://
Click here to trigger a rebuild:
http://
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.
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:/
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.
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:420
http://
Executed test runs:
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:420
http://
Executed test runs:
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:422
http://
Executed test runs:
SUCCESS: http://
Click here to trigger a rebuild:
http://
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")?
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.
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.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:423
http://
Executed test runs:
SUCCESS: http://
Click here to trigger a rebuild:
http://
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.
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.
Chris Halse Rogers (raof) wrote : | # |
This approach makes callback-based code slightly more annoying - it becomes
mir_callback_
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.
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
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 | +} |
PASSED: Continuous integration, rev:413 s-jenkins: 8080/job/ mir-ci/ 1085/ s-jenkins: 8080/job/ mir-ci/ ./build= pbuilder, distribution= quantal, flavor= amd64/1085/ console
http://
Executed test runs:
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins: 8080/job/ mir-ci/ 1085//rebuild/?
http://