Mir

Merge lp:~alan-griffiths/mir/improve-tidy-up-of-mir_connection_get_display_info into lp:mir

Proposed by Alan Griffiths
Status: Merged
Merged at revision: 1157
Proposed branch: lp:~alan-griffiths/mir/improve-tidy-up-of-mir_connection_get_display_info
Merge into: lp:mir
Diff against target: 109 lines (+51/-45)
1 file modified
src/client/mir_client_library.cpp (+51/-45)
To merge this branch: bzr merge lp:~alan-griffiths/mir/improve-tidy-up-of-mir_connection_get_display_info
Reviewer Review Type Date Requested Status
Alexandros Frantzis (community) Approve
Daniel van Vugt Disapprove
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+190134@code.launchpad.net

Commit message

client: RAII version of ~alan-griffiths/mir/lock_guard-for-unique_lock

Description of the change

client: RAII version of ~alan-griffiths/mir/lock_guard-for-unique_lock

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

I think this is a step backwards. The first hint is the increase in code size (+19/-9). But more importantly, this is difficult to read: unique_with_deleter. Much more difficult to read than the "mir_display_config_destroy(config)" you're aiming to replace. I would rather keep the code readable with mir_display_config_destroy.

RAII is not useful if it results in code that's less clear about the possibility of leaks than that which it replaces. And I think mir_connection_get_display_info is presently very clear on the lifetime of config.

Also, there are a few unrelated whitespace changes in src/client/mir_client_library.cpp.

review: Disapprove
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

> I think this is a step backwards. The first hint is the increase in code size
> (+19/-9). But more importantly, this is difficult to read:
> unique_with_deleter. Much more difficult to read than the
> "mir_display_config_destroy(config)" you're aiming to replace. I would rather
> keep the code readable with mir_display_config_destroy.

You're missing that it fixes the leaks caused by "return" statements that bypass that call. Alternative fixes also add lines.

> RAII is not useful if it results in code that's less clear about the
> possibility of leaks than that which it replaces. And I think
> mir_connection_get_display_info is presently very clear on the lifetime of
> config.

A RAII version was requested by Thomas and Alf - an alternative fix (that I was happy) with has already landed.

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

There are no return statements. The flow of mir_connection_get_display_info is very clear as it's not a long function.

I favour explicit deletion over implicit, if the latter is significantly more cryptic (as it is here).

But other people may disagree.

Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

> There are no return statements. The flow of mir_connection_get_display_info is
> very clear as it's not a long function.

There were in the version you referred to in "the increase in code size (+19/-9)." The alternative fix I mentioned removed them (-c 1120 on development-branch).

Explicit deletion is problematic in the presence of exceptions (which shouldn't apply here) or return statements (which we've just discussed).

It is reasonable to prefer uniform use of RAII for cleanup.

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

> RAII is not useful if it results in code that's less clear about the possibility of leaks
> than that which it replaces.

In this case (and in general) RAII minimizes the possibility of leaks now and in the future.

A reasonable alternative approach not using RAII, like r1120 on development-branch, is both more cumbersome than this and is not future-proof. What if the function gradually gets more complicated? What if someone inadvertently adds a return? We didn't catch this last time, we may not catch it the next.

Plus, we are using RAII/smart pointers all over the place, I don't see a reason to make an exception here.

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

I don't think one can talk about "future proof" at the same time as making code less readable. If it's less readable, you're cursing future maintainers to either not comprehend the code (so can't maintain it and/or waste time), or to misunderstand it and introduce regressions. Leaks are not the only kind of bug, and having readable code is a better preventative measure. In fact, leaks are much less important and less severe than many of the conceivable outcomes of a future maintainer not understanding the code.

Revision history for this message
Kevin DuBois (kdub) wrote :

I think this is okay. Perhaps it would be more immediately readable if lines 51-53 were just a shared_ptr with a deleter though (less figuring out what the inlined function is doing). I do think raii is the right way to fix the problem, but can empathize with wanting to figure out less types of pointers.

Revision history for this message
kevin gunn (kgunn72) wrote :

granted i don't touch code everyday, but it does seem to me that RAII is an accepted paradigm that was created to avoid orphaning objects from an owning objects excpetion (...a good thing)
at the same time, Could some additional pointed comments be added to the code to solve the maintainability concern ?

note...i don't agree that we should look at code size generically as a measuring stick...i've certainly seen it go the other way where people trying to "shrink" code made it more enigmatic.

I would propose some comments to be added as to what the deleter is doing, how it helps in the exception instance...then call this good

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

My disapproval is only about style and readability. Please treat it like "Abstain" so we don't waste any more time arguing. I fully expect this to land still.

Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

I'm hearing that some folks would prefer losing the helper function and:

    std::unique_ptr<MirDisplayConfiguration, decltype(&mir_display_config_destroy)> const config(

to:

    auto const config = unique_with_deleter(

I guess it is a trade off between syntactic noise and an unfamiliar helper function. Let me know.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/client/mir_client_library.cpp'
2--- src/client/mir_client_library.cpp 2013-10-17 05:51:24 +0000
3+++ src/client/mir_client_library.cpp 2013-10-17 10:51:13 +0000
4@@ -289,54 +289,60 @@
5 mcl::delete_config_storage(configuration);
6 }
7
8+namespace
9+{
10+template <typename Owned>
11+inline std::unique_ptr<Owned, void(*)(Owned*)> unique_with_deleter(Owned* owned, void(*deleter)(Owned*))
12+{
13+ return {owned, deleter};
14+}
15+}
16+
17 //TODO: DEPRECATED: remove this function
18 void mir_connection_get_display_info(MirConnection *connection, MirDisplayInfo *display_info)
19 {
20- auto config = mir_connection_create_display_config(connection);
21-
22- do
23- {
24- if (config->num_outputs < 1)
25- break;
26-
27- MirDisplayOutput* state = nullptr;
28- // We can't handle more than one display, so just populate based on the first
29- // active display we find.
30- for (unsigned int i = 0; i < config->num_outputs; ++i)
31- {
32- if (config->outputs[i].used && config->outputs[i].connected &&
33- config->outputs[i].current_mode < config->outputs[i].num_modes)
34- {
35- state = &config->outputs[i];
36- break;
37- }
38- }
39- // Oh, oh! No connected outputs?!
40- if (state == nullptr)
41- {
42- memset(display_info, 0, sizeof(*display_info));
43- break;
44- }
45-
46- MirDisplayMode mode = state->modes[state->current_mode];
47-
48- display_info->width = mode.horizontal_resolution;
49- display_info->height = mode.vertical_resolution;
50-
51- unsigned int format_items;
52- if (state->num_output_formats > mir_supported_pixel_format_max)
53- format_items = mir_supported_pixel_format_max;
54- else
55- format_items = state->num_output_formats;
56-
57- display_info->supported_pixel_format_items = format_items;
58- for(auto i=0u; i < format_items; i++)
59- {
60- display_info->supported_pixel_format[i] = state->output_formats[i];
61- }
62- } while (false);
63-
64- mir_display_config_destroy(config);
65+ auto const config = unique_with_deleter(
66+ mir_connection_create_display_config(connection),
67+ &mir_display_config_destroy);
68+
69+ if (config->num_outputs < 1)
70+ return;
71+
72+ MirDisplayOutput* state = nullptr;
73+ // We can't handle more than one display, so just populate based on the first
74+ // active display we find.
75+ for (unsigned int i = 0; i < config->num_outputs; ++i)
76+ {
77+ if (config->outputs[i].used && config->outputs[i].connected &&
78+ config->outputs[i].current_mode < config->outputs[i].num_modes)
79+ {
80+ state = &config->outputs[i];
81+ break;
82+ }
83+ }
84+ // Oh, oh! No connected outputs?!
85+ if (state == nullptr)
86+ {
87+ memset(display_info, 0, sizeof(*display_info));
88+ return;
89+ }
90+
91+ MirDisplayMode mode = state->modes[state->current_mode];
92+
93+ display_info->width = mode.horizontal_resolution;
94+ display_info->height = mode.vertical_resolution;
95+
96+ unsigned int format_items;
97+ if (state->num_output_formats > mir_supported_pixel_format_max)
98+ format_items = mir_supported_pixel_format_max;
99+ else
100+ format_items = state->num_output_formats;
101+
102+ display_info->supported_pixel_format_items = format_items;
103+ for(auto i=0u; i < format_items; i++)
104+ {
105+ display_info->supported_pixel_format[i] = state->output_formats[i];
106+ }
107 }
108
109 void mir_surface_get_graphics_region(MirSurface * surface, MirGraphicsRegion * graphics_region)

Subscribers

People subscribed via source and target branches