[Spice-devel] [PATCH v3] Simplify current_add_equal loop
Frediano Ziglio
fziglio at redhat.com
Tue May 24 10:19:00 UTC 2016
With some simple steps I simplified the internal loop of this
function
* convert to infinite loop
/* dpi contains a sublist of dcc's, ordered the same */
while (worker_ring_item) {
dcc = SPICE_CONTAINEROF(worker_ring_item, DisplayChannelClient,
common.base.channel_link);
dpi = SPICE_CONTAINEROF(dpi_ring_item, RedDrawablePipeItem, base);
- while (worker_ring_item && (!dpi || dcc != dpi->dcc)) {
+ for (;;) {
+ if (!worker_ring_item || (dpi && dcc == dpi->dcc)) {
+ break;
+ }
dcc_prepend_drawable(dcc, drawable);
worker_ring_item = ring_next(&RED_CHANNEL(display)->clients,
worker_ring_item);
dcc = SPICE_CONTAINEROF(worker_ring_item, DisplayChannelClient,
* split if
while (worker_ring_item) {
dcc = SPICE_CONTAINEROF(worker_ring_item, DisplayChannelClient,
common.base.channel_link);
dpi = SPICE_CONTAINEROF(dpi_ring_item, RedDrawablePipeItem, base);
for (;;) {
- if (!worker_ring_item || (dpi && dcc == dpi->dcc)) {
+ if (!worker_ring_item) {
+ break;
+ }
+ if (dpi && dcc == dpi->dcc) {
break;
}
dcc_prepend_drawable(dcc, drawable);
worker_ring_item = ring_next(&RED_CHANNEL(display)->clients,
worker_ring_item);
* the worker_ring_item condition make this case terminate loop
dpi_ring_item is changed but ignored
dcc = SPICE_CONTAINEROF(worker_ring_item, DisplayChannelClient,
common.base.channel_link);
dpi = SPICE_CONTAINEROF(dpi_ring_item, RedDrawablePipeItem, base);
for (;;) {
if (!worker_ring_item) {
- break;
+ goto out_loop;
}
if (dpi && dcc == dpi->dcc) {
break;
}
dcc_prepend_drawable(dcc, drawable);
worker_ring_item = ring_next(&RED_CHANNEL(display)->clients,
worker_ring_item);
dpi_ring_item = ring_next(&other_drawable->pipes, dpi_ring_item);
}
if (worker_ring_item) {
worker_ring_item = ring_next(&RED_CHANNEL(display)->clients,
worker_ring_item);
}
}
+out_loop:
/* not sending other_drawable where possible */
drawable_remove_from_pipes(other_drawable);
drawable_unref(other_drawable);
return TRUE;
* worker_ring_item is never null here
if (dpi_ring_item) {
dpi_ring_item = ring_next(&other_drawable->pipes, dpi_ring_item);
}
- if (worker_ring_item) {
- worker_ring_item = ring_next(&RED_CHANNEL(display)->clients,
- worker_ring_item);
- }
+ worker_ring_item = ring_next(&RED_CHANNEL(display)->clients,
+ worker_ring_item);
}
out_loop:
/* not sending other_drawable where possible */
drawable_remove_from_pipes(other_drawable);
* dcc used is always a value from current worker_ring_item
worker_ring_item = ring_get_head(&RED_CHANNEL(display)->clients);
dpi_ring_item = ring_get_head(&other_drawable->pipes);
/* dpi contains a sublist of dcc's, ordered the same */
while (worker_ring_item) {
- dcc = SPICE_CONTAINEROF(worker_ring_item, DisplayChannelClient,
- common.base.channel_link);
dpi = SPICE_CONTAINEROF(dpi_ring_item, RedDrawablePipeItem, base);
for (;;) {
if (!worker_ring_item) {
goto out_loop;
}
+ dcc = SPICE_CONTAINEROF(worker_ring_item, DisplayChannelClient,
+ common.base.channel_link);
if (dpi && dcc == dpi->dcc) {
break;
}
dcc_prepend_drawable(dcc, drawable);
worker_ring_item = ring_next(&RED_CHANNEL(display)->clients,
worker_ring_item);
- dcc = SPICE_CONTAINEROF(worker_ring_item, DisplayChannelClient,
- common.base.channel_link);
}
if (dpi_ring_item) {
dpi_ring_item = ring_next(&other_drawable->pipes, dpi_ring_item);
}
* move code inside if
these lines are only executed then the condition are satisfied
goto out_loop;
}
dcc = SPICE_CONTAINEROF(worker_ring_item, DisplayChannelClient,
common.base.channel_link);
if (dpi && dcc == dpi->dcc) {
+ if (dpi_ring_item) {
+ dpi_ring_item = ring_next(&other_drawable->pipes, dpi_ring_item);
+ }
+ worker_ring_item = ring_next(&RED_CHANNEL(display)->clients,
+ worker_ring_item);
break;
}
dcc_prepend_drawable(dcc, drawable);
worker_ring_item = ring_next(&RED_CHANNEL(display)->clients,
worker_ring_item);
}
-
- if (dpi_ring_item) {
- dpi_ring_item = ring_next(&other_drawable->pipes, dpi_ring_item);
- }
- worker_ring_item = ring_next(&RED_CHANNEL(display)->clients,
- worker_ring_item);
}
out_loop:
/* not sending other_drawable where possible */
drawable_remove_from_pipes(other_drawable);
* dpi is always a value computed from dpi_ring_item
worker_ring_item = ring_get_head(&RED_CHANNEL(display)->clients);
dpi_ring_item = ring_get_head(&other_drawable->pipes);
/* dpi contains a sublist of dcc's, ordered the same */
while (worker_ring_item) {
- dpi = SPICE_CONTAINEROF(dpi_ring_item, RedDrawablePipeItem, base);
for (;;) {
if (!worker_ring_item) {
goto out_loop;
}
dcc = SPICE_CONTAINEROF(worker_ring_item, DisplayChannelClient,
common.base.channel_link);
+ dpi = SPICE_CONTAINEROF(dpi_ring_item, RedDrawablePipeItem, base);
if (dpi && dcc == dpi->dcc) {
if (dpi_ring_item) {
dpi_ring_item = ring_next(&other_drawable->pipes, dpi_ring_item);
}
worker_ring_item = ring_next(&RED_CHANNEL(display)->clients,
* if dpi is not NULL even dpi_ring_item is not NULL
dcc = SPICE_CONTAINEROF(worker_ring_item, DisplayChannelClient,
common.base.channel_link);
dpi = SPICE_CONTAINEROF(dpi_ring_item, RedDrawablePipeItem, base);
if (dpi && dcc == dpi->dcc) {
- if (dpi_ring_item) {
- dpi_ring_item = ring_next(&other_drawable->pipes, dpi_ring_item);
- }
+ dpi_ring_item = ring_next(&other_drawable->pipes, dpi_ring_item);
worker_ring_item = ring_next(&RED_CHANNEL(display)->clients,
worker_ring_item);
break;
}
dcc_prepend_drawable(dcc, drawable);
* if worker_ring_item is NULL jumping outside loop will check
variable and exit
The outer loop would exit too.
dpi_ring_item = ring_get_head(&other_drawable->pipes);
/* dpi contains a sublist of dcc's, ordered the same */
while (worker_ring_item) {
for (;;) {
if (!worker_ring_item) {
- goto out_loop;
+ break;
}
dcc = SPICE_CONTAINEROF(worker_ring_item, DisplayChannelClient,
common.base.channel_link);
dpi = SPICE_CONTAINEROF(dpi_ring_item, RedDrawablePipeItem, base);
if (dpi && dcc == dpi->dcc) {
dpi_ring_item = ring_next(&other_drawable->pipes, dpi_ring_item);
worker_ring_item = ring_next(&RED_CHANNEL(display)->clients,
break;
}
dcc_prepend_drawable(dcc, drawable);
worker_ring_item = ring_next(&RED_CHANNEL(display)->clients,
worker_ring_item);
}
}
-out_loop:
/* not sending other_drawable where possible */
drawable_remove_from_pipes(other_drawable);
drawable_unref(other_drawable);
return TRUE;
* use while again
Convert from for(;;) { if () break; ... } to while
worker_ring_item = ring_get_head(&RED_CHANNEL(display)->clients);
dpi_ring_item = ring_get_head(&other_drawable->pipes);
/* dpi contains a sublist of dcc's, ordered the same */
while (worker_ring_item) {
- for (;;) {
- if (!worker_ring_item) {
- break;
- }
+ while (worker_ring_item) {
dcc = SPICE_CONTAINEROF(worker_ring_item, DisplayChannelClient,
common.base.channel_link);
dpi = SPICE_CONTAINEROF(dpi_ring_item, RedDrawablePipeItem, base);
if (dpi && dcc == dpi->dcc) {
dpi_ring_item = ring_next(&other_drawable->pipes, dpi_ring_item);
* convert break to continue
Both jump to check worker_ring_item (internal or external loops)
dpi = SPICE_CONTAINEROF(dpi_ring_item, RedDrawablePipeItem, base);
if (dpi && dcc == dpi->dcc) {
dpi_ring_item = ring_next(&other_drawable->pipes, dpi_ring_item);
worker_ring_item = ring_next(&RED_CHANNEL(display)->clients,
worker_ring_item);
- break;
+ continue;
}
dcc_prepend_drawable(dcc, drawable);
worker_ring_item = ring_next(&RED_CHANNEL(display)->clients,
worker_ring_item);
}
* reuse code inside loop
dcc = SPICE_CONTAINEROF(worker_ring_item, DisplayChannelClient,
common.base.channel_link);
dpi = SPICE_CONTAINEROF(dpi_ring_item, RedDrawablePipeItem, base);
if (dpi && dcc == dpi->dcc) {
dpi_ring_item = ring_next(&other_drawable->pipes, dpi_ring_item);
- worker_ring_item = ring_next(&RED_CHANNEL(display)->clients,
- worker_ring_item);
- continue;
+ } else {
+ dcc_prepend_drawable(dcc, drawable);
}
- dcc_prepend_drawable(dcc, drawable);
worker_ring_item = ring_next(&RED_CHANNEL(display)->clients,
worker_ring_item);
}
}
* join the two loop
They tested the same condition, no break in inside loop (which would
exit all loops)
worker_ring_item = ring_get_head(&RED_CHANNEL(display)->clients);
dpi_ring_item = ring_get_head(&other_drawable->pipes);
/* dpi contains a sublist of dcc's, ordered the same */
while (worker_ring_item) {
- while (worker_ring_item) {
- dcc = SPICE_CONTAINEROF(worker_ring_item, DisplayChannelClient,
- common.base.channel_link);
- dpi = SPICE_CONTAINEROF(dpi_ring_item, RedDrawablePipeItem, base);
- if (dpi && dcc == dpi->dcc) {
- dpi_ring_item = ring_next(&other_drawable->pipes, dpi_ring_item);
- } else {
- dcc_prepend_drawable(dcc, drawable);
- }
- worker_ring_item = ring_next(&RED_CHANNEL(display)->clients,
- worker_ring_item);
+ dcc = SPICE_CONTAINEROF(worker_ring_item, DisplayChannelClient,
+ common.base.channel_link);
+ dpi = SPICE_CONTAINEROF(dpi_ring_item, RedDrawablePipeItem, base);
+ if (dpi && dcc == dpi->dcc) {
+ dpi_ring_item = ring_next(&other_drawable->pipes, dpi_ring_item);
+ } else {
+ dcc_prepend_drawable(dcc, drawable);
}
+ worker_ring_item = ring_next(&RED_CHANNEL(display)->clients,
+ worker_ring_item);
}
/* not sending other_drawable where possible */
drawable_remove_from_pipes(other_drawable);
drawable_unref(other_drawable);
* inline dpi computation
Actually not exactly the same as this fix a bug if base is not the
first element (in this case if dpi_ring_item is NULL dpi is not)
switch (item->effect) {
case QXL_EFFECT_REVERT_ON_DUP:
if (is_same_drawable(drawable, other_drawable)) {
DisplayChannelClient *dcc;
- RedDrawablePipeItem *dpi;
RingItem *worker_ring_item, *dpi_ring_item;
other_drawable->refs++;
current_remove_drawable(display, other_drawable);
/* sending the drawable to clients that already received
* (or will receive) other_drawable */
worker_ring_item = ring_get_head(&RED_CHANNEL(display)->clients);
dpi_ring_item = ring_get_head(&other_drawable->pipes);
/* dpi contains a sublist of dcc's, ordered the same */
while (worker_ring_item) {
dcc = SPICE_CONTAINEROF(worker_ring_item, DisplayChannelClient,
common.base.channel_link);
- dpi = SPICE_CONTAINEROF(dpi_ring_item, RedDrawablePipeItem, base);
- if (dpi && dcc == dpi->dcc) {
+ if (dpi_ring_item && dcc == SPICE_CONTAINEROF(dpi_ring_item, RedDrawablePipeItem, base)->dcc) {
dpi_ring_item = ring_next(&other_drawable->pipes, dpi_ring_item);
} else {
dcc_prepend_drawable(dcc, drawable);
}
worker_ring_item = ring_next(&RED_CHANNEL(display)->clients,
* use RING_FOREACH macro for loop
other_drawable->refs++;
current_remove_drawable(display, other_drawable);
/* sending the drawable to clients that already received
* (or will receive) other_drawable */
- worker_ring_item = ring_get_head(&RED_CHANNEL(display)->clients);
dpi_ring_item = ring_get_head(&other_drawable->pipes);
/* dpi contains a sublist of dcc's, ordered the same */
- while (worker_ring_item) {
+ RING_FOREACH (worker_ring_item, &RED_CHANNEL(display)->clients) {
dcc = SPICE_CONTAINEROF(worker_ring_item, DisplayChannelClient,
common.base.channel_link);
if (dpi_ring_item && dcc == SPICE_CONTAINEROF(dpi_ring_item, RedDrawablePipeItem, base)->dcc) {
dpi_ring_item = ring_next(&other_drawable->pipes, dpi_ring_item);
} else {
dcc_prepend_drawable(dcc, drawable);
}
- worker_ring_item = ring_next(&RED_CHANNEL(display)->clients,
- worker_ring_item);
}
/* not sending other_drawable where possible */
drawable_remove_from_pipes(other_drawable);
drawable_unref(other_drawable);
Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
---
server/display-channel.c | 21 ++++-----------------
1 file changed, 4 insertions(+), 17 deletions(-)
Changes from v2:
- update comment, some notes were missing.
diff --git a/server/display-channel.c b/server/display-channel.c
index 96a6f2f..6d459fe 100644
--- a/server/display-channel.c
+++ b/server/display-channel.c
@@ -464,7 +464,6 @@ static int current_add_equal(DisplayChannel *display, DrawItem *item, TreeItem *
if (is_same_drawable(drawable, other_drawable)) {
DisplayChannelClient *dcc;
- RedDrawablePipeItem *dpi;
RingItem *worker_ring_item, *dpi_ring_item;
other_drawable->refs++;
@@ -472,27 +471,15 @@ static int current_add_equal(DisplayChannel *display, DrawItem *item, TreeItem *
/* sending the drawable to clients that already received
* (or will receive) other_drawable */
- worker_ring_item = ring_get_head(&RED_CHANNEL(display)->clients);
dpi_ring_item = ring_get_head(&other_drawable->pipes);
/* dpi contains a sublist of dcc's, ordered the same */
- while (worker_ring_item) {
+ RING_FOREACH (worker_ring_item, &RED_CHANNEL(display)->clients) {
dcc = SPICE_CONTAINEROF(worker_ring_item, DisplayChannelClient,
common.base.channel_link);
- dpi = SPICE_CONTAINEROF(dpi_ring_item, RedDrawablePipeItem, base);
- while (worker_ring_item && (!dpi || dcc != dpi->dcc)) {
- dcc_prepend_drawable(dcc, drawable);
- worker_ring_item = ring_next(&RED_CHANNEL(display)->clients,
- worker_ring_item);
- dcc = SPICE_CONTAINEROF(worker_ring_item, DisplayChannelClient,
- common.base.channel_link);
- }
-
- if (dpi_ring_item) {
+ if (dpi_ring_item && dcc == SPICE_CONTAINEROF(dpi_ring_item, RedDrawablePipeItem, base)->dcc) {
dpi_ring_item = ring_next(&other_drawable->pipes, dpi_ring_item);
- }
- if (worker_ring_item) {
- worker_ring_item = ring_next(&RED_CHANNEL(display)->clients,
- worker_ring_item);
+ } else {
+ dcc_prepend_drawable(dcc, drawable);
}
}
/* not sending other_drawable where possible */
--
2.7.4
More information about the Spice-devel
mailing list