Use more reference counting on RedPipeItem

This is the continuation of Christophe patches using reference
counting for RedPipeItem.
Extend it's usage.
This for instance leads to the removal of release_item callback.
This commit is contained in:
Frediano Ziglio 2016-05-18 00:22:43 +01:00
commit e72fec2289
14 changed files with 81 additions and 271 deletions

View File

@ -48,7 +48,6 @@ G_STATIC_ASSERT(sizeof(CursorItem) <= QXL_CURSUR_DEVICE_DATA_SIZE);
typedef struct RedCursorPipeItem {
RedPipeItem base;
CursorItem *cursor_item;
int refs;
} RedCursorPipeItem;
struct CursorChannel {
@ -82,6 +81,8 @@ struct CursorChannelClient {
#include "cache-item.tmpl.c"
#undef CLIENT_CURSOR_CACHE
static void cursor_pipe_item_free(RedCursorPipeItem *pipe_item);
static CursorItem *cursor_item_new(QXLInstance *qxl, RedCursorCmd *cmd)
{
CursorItem *cursor_item;
@ -136,8 +137,8 @@ static RedPipeItem *new_cursor_pipe_item(RedChannelClient *rcc, void *data, int
{
RedCursorPipeItem *item = spice_malloc0(sizeof(RedCursorPipeItem));
red_pipe_item_init(&item->base, RED_PIPE_ITEM_TYPE_CURSOR);
item->refs = 1;
red_pipe_item_init_full(&item->base, RED_PIPE_ITEM_TYPE_CURSOR,
(GDestroyNotify)cursor_pipe_item_free);
item->cursor_item = data;
item->cursor_item->refs++;
return &item->base;
@ -203,15 +204,9 @@ void cursor_channel_disconnect(CursorChannel *cursor_channel)
}
static void put_cursor_pipe_item(CursorChannelClient *ccc,
RedCursorPipeItem *pipe_item)
static void cursor_pipe_item_free(RedCursorPipeItem *pipe_item)
{
spice_return_if_fail(pipe_item);
spice_return_if_fail(pipe_item->refs > 0);
if (--pipe_item->refs) {
return;
}
spice_assert(!red_pipe_item_is_linked(&pipe_item->base));
@ -227,42 +222,6 @@ static void cursor_channel_client_on_disconnect(RedChannelClient *rcc)
red_reset_cursor_cache(rcc);
}
// TODO: share code between before/after_push since most of the items need the same
// release
static void cursor_channel_client_release_item_before_push(CursorChannelClient *ccc,
RedPipeItem *item)
{
switch (item->type) {
case RED_PIPE_ITEM_TYPE_CURSOR: {
RedCursorPipeItem *cursor_pipe_item = SPICE_CONTAINEROF(item, RedCursorPipeItem, base);
put_cursor_pipe_item(ccc, cursor_pipe_item);
break;
}
case RED_PIPE_ITEM_TYPE_INVAL_ONE:
case RED_PIPE_ITEM_TYPE_VERB:
case RED_PIPE_ITEM_TYPE_CURSOR_INIT:
case RED_PIPE_ITEM_TYPE_INVAL_CURSOR_CACHE:
free(item);
break;
default:
spice_error("invalid pipe item type");
}
}
static void cursor_channel_client_release_item_after_push(CursorChannelClient *ccc,
RedPipeItem *item)
{
switch (item->type) {
case RED_PIPE_ITEM_TYPE_CURSOR: {
RedCursorPipeItem *cursor_pipe_item = SPICE_CONTAINEROF(item, RedCursorPipeItem, base);
put_cursor_pipe_item(ccc, cursor_pipe_item);
break;
}
default:
spice_critical("invalid item type");
}
}
static void red_marshall_cursor_init(RedChannelClient *rcc, SpiceMarshaller *base_marshaller,
RedPipeItem *pipe_item)
{
@ -354,7 +313,6 @@ static inline void red_marshall_inval(RedChannelClient *rcc,
static void cursor_channel_send_item(RedChannelClient *rcc, RedPipeItem *pipe_item)
{
SpiceMarshaller *m = red_channel_client_get_marshaller(rcc);
CursorChannelClient *ccc = RCC_TO_CCC(rcc);
switch (pipe_item->type) {
case RED_PIPE_ITEM_TYPE_CURSOR:
@ -378,16 +336,15 @@ static void cursor_channel_send_item(RedChannelClient *rcc, RedPipeItem *pipe_it
spice_error("invalid pipe item type");
}
cursor_channel_client_release_item_before_push(ccc, pipe_item);
red_pipe_item_unref(pipe_item);
red_channel_client_begin_send_message(rcc);
}
static RedCursorPipeItem *cursor_pipe_item_ref(RedCursorPipeItem *item)
{
spice_return_val_if_fail(item, NULL);
spice_return_val_if_fail(item->refs > 0, NULL);
item->refs++;
red_pipe_item_ref(item);
return item;
}
@ -402,20 +359,6 @@ static void cursor_channel_hold_pipe_item(RedChannelClient *rcc, RedPipeItem *it
cursor_pipe_item_ref(cursor_pipe_item);
}
static void cursor_channel_release_item(RedChannelClient *rcc, RedPipeItem *item, int item_pushed)
{
CursorChannelClient *ccc = RCC_TO_CCC(rcc);
spice_assert(item);
if (item_pushed) {
cursor_channel_client_release_item_after_push(ccc, item);
} else {
spice_debug("not pushed (%d)", item->type);
cursor_channel_client_release_item_before_push(ccc, item);
}
}
CursorChannel* cursor_channel_new(RedWorker *worker)
{
CursorChannel *cursor_channel;
@ -424,7 +367,6 @@ CursorChannel* cursor_channel_new(RedWorker *worker)
.on_disconnect = cursor_channel_client_on_disconnect,
.send_item = cursor_channel_send_item,
.hold_item = cursor_channel_hold_pipe_item,
.release_item = cursor_channel_release_item
};
spice_info("create cursor channel");

View File

@ -2383,8 +2383,8 @@ void dcc_send_item(DisplayChannelClient *dcc, RedPipeItem *pipe_item)
marshall_inval_palette(rcc, m, (RedCacheItem *)pipe_item);
break;
case RED_PIPE_ITEM_TYPE_STREAM_CREATE: {
StreamAgent *agent = SPICE_CONTAINEROF(pipe_item, StreamAgent, create_item);
marshall_stream_start(rcc, m, agent);
StreamCreateDestroyItem *item = SPICE_CONTAINEROF(pipe_item, StreamCreateDestroyItem, base);
marshall_stream_start(rcc, m, item->agent);
break;
}
case RED_PIPE_ITEM_TYPE_STREAM_CLIP: {
@ -2393,8 +2393,8 @@ void dcc_send_item(DisplayChannelClient *dcc, RedPipeItem *pipe_item)
break;
}
case RED_PIPE_ITEM_TYPE_STREAM_DESTROY: {
StreamAgent *agent = SPICE_CONTAINEROF(pipe_item, StreamAgent, destroy_item);
marshall_stream_end(rcc, m, agent);
StreamCreateDestroyItem *item = SPICE_CONTAINEROF(pipe_item, StreamCreateDestroyItem, base);
marshall_stream_end(rcc, m, item->agent);
break;
}
case RED_PIPE_ITEM_TYPE_UPGRADE:
@ -2455,7 +2455,7 @@ void dcc_send_item(DisplayChannelClient *dcc, RedPipeItem *pipe_item)
spice_warn_if_reached();
}
dcc_release_item(dcc, pipe_item, FALSE);
red_pipe_item_unref(pipe_item);
// a message is pending
if (red_channel_client_send_message_pending(rcc)) {

View File

@ -288,7 +288,9 @@ void red_drawable_pipe_item_free(RedPipeItem *item)
spice_assert(item->refcount == 0);
spice_warn_if_fail(!ring_item_is_linked(&item->link));
spice_warn_if_fail(!ring_item_is_linked(&dpi->base));
if (ring_item_is_linked(&dpi->base)) {
ring_remove(&dpi->base);
}
drawable_unref(dpi->drawable);
free(dpi);
}
@ -343,8 +345,6 @@ static void dcc_init_stream_agents(DisplayChannelClient *dcc)
agent->stream = &display->streams_buf[i];
region_init(&agent->vis_region);
region_init(&agent->clip);
red_pipe_item_init(&agent->create_item, RED_PIPE_ITEM_TYPE_STREAM_CREATE);
red_pipe_item_init(&agent->destroy_item, RED_PIPE_ITEM_TYPE_STREAM_DESTROY);
}
dcc->use_video_encoder_rate_control =
red_channel_client_test_remote_cap(RED_CHANNEL_CLIENT(dcc), SPICE_DISPLAY_CAP_STREAM_REPORT);
@ -1607,89 +1607,3 @@ int dcc_handle_migrate_data(DisplayChannelClient *dcc, uint32_t size, void *mess
red_channel_client_ack_zero_messages_window(RED_CHANNEL_CLIENT(dcc));
return TRUE;
}
static void release_item_after_push(RedPipeItem *item)
{
switch (item->type) {
case RED_PIPE_ITEM_TYPE_DRAW:
case RED_PIPE_ITEM_TYPE_IMAGE:
case RED_PIPE_ITEM_TYPE_STREAM_CLIP:
case RED_PIPE_ITEM_TYPE_MONITORS_CONFIG:
case RED_PIPE_ITEM_TYPE_UPGRADE:
red_pipe_item_unref(item);
break;
case RED_PIPE_ITEM_TYPE_GL_SCANOUT:
case RED_PIPE_ITEM_TYPE_GL_DRAW:
case RED_PIPE_ITEM_TYPE_VERB:
free(item);
break;
default:
spice_critical("invalid item type");
}
}
// TODO: share code between before/after_push since most of the items need the same
// release
static void release_item_before_push(DisplayChannelClient *dcc, RedPipeItem *item)
{
DisplayChannel *display = DCC_TO_DC(dcc);
spice_debug("item.type: %d", item->type);
switch (item->type) {
case RED_PIPE_ITEM_TYPE_DRAW: {
RedDrawablePipeItem *dpi = SPICE_CONTAINEROF(item, RedDrawablePipeItem, dpi_pipe_item);
ring_remove(&dpi->base);
red_pipe_item_unref(item);
break;
}
case RED_PIPE_ITEM_TYPE_STREAM_CREATE: {
StreamAgent *agent = SPICE_CONTAINEROF(item, StreamAgent, create_item);
stream_agent_unref(display, agent);
break;
}
case RED_PIPE_ITEM_TYPE_STREAM_DESTROY: {
StreamAgent *agent = SPICE_CONTAINEROF(item, StreamAgent, destroy_item);
stream_agent_unref(display, agent);
break;
}
case RED_PIPE_ITEM_TYPE_STREAM_CLIP:
case RED_PIPE_ITEM_TYPE_UPGRADE:
case RED_PIPE_ITEM_TYPE_IMAGE:
case RED_PIPE_ITEM_TYPE_MONITORS_CONFIG:
red_pipe_item_unref(item);
break;
case RED_PIPE_ITEM_TYPE_CREATE_SURFACE: {
RedSurfaceCreateItem *surface_create = SPICE_CONTAINEROF(item, RedSurfaceCreateItem,
pipe_item);
free(surface_create);
break;
}
case RED_PIPE_ITEM_TYPE_DESTROY_SURFACE: {
RedSurfaceDestroyItem *surface_destroy = SPICE_CONTAINEROF(item, RedSurfaceDestroyItem,
pipe_item);
free(surface_destroy);
break;
}
case RED_PIPE_ITEM_TYPE_INVAL_ONE:
case RED_PIPE_ITEM_TYPE_VERB:
case RED_PIPE_ITEM_TYPE_MIGRATE_DATA:
case RED_PIPE_ITEM_TYPE_PIXMAP_SYNC:
case RED_PIPE_ITEM_TYPE_PIXMAP_RESET:
case RED_PIPE_ITEM_TYPE_INVAL_PALETTE_CACHE:
case RED_PIPE_ITEM_TYPE_STREAM_ACTIVATE_REPORT:
case RED_PIPE_ITEM_TYPE_GL_SCANOUT:
case RED_PIPE_ITEM_TYPE_GL_DRAW:
free(item);
break;
default:
spice_critical("invalid item type");
}
}
void dcc_release_item(DisplayChannelClient *dcc, RedPipeItem *item, int item_pushed)
{
if (item_pushed)
release_item_after_push(item);
else
release_item_before_push(dcc, item);
}

View File

@ -122,8 +122,8 @@ struct DisplayChannelClient {
#define RCC_TO_DCC(rcc) SPICE_CONTAINEROF((rcc), DisplayChannelClient, common.base)
typedef struct RedSurfaceCreateItem {
SpiceMsgSurfaceCreate surface_create;
RedPipeItem pipe_item;
SpiceMsgSurfaceCreate surface_create;
} RedSurfaceCreateItem;
typedef struct RedGlScanoutUnixItem {
@ -154,7 +154,6 @@ typedef struct RedDrawablePipeItem {
RedPipeItem dpi_pipe_item; /* link for the client's pipe itself */
Drawable *drawable;
DisplayChannelClient *dcc;
uint8_t refs;
} RedDrawablePipeItem;
DisplayChannelClient* dcc_new (DisplayChannel *display,
@ -204,9 +203,6 @@ void dcc_append_drawable (DisplayCha
void dcc_add_drawable_after (DisplayChannelClient *dcc,
Drawable *drawable,
RedPipeItem *pos);
void dcc_release_item (DisplayChannelClient *dcc,
RedPipeItem *item,
int item_pushed);
void dcc_send_item (DisplayChannelClient *dcc,
RedPipeItem *item);
int dcc_clear_surface_drawables_from_pipe (DisplayChannelClient *dcc,

View File

@ -1946,14 +1946,6 @@ static void hold_item(RedChannelClient *rcc, RedPipeItem *item)
}
}
static void release_item(RedChannelClient *rcc, RedPipeItem *item, int item_pushed)
{
DisplayChannelClient *dcc = RCC_TO_DCC(rcc);
spice_return_if_fail(item != NULL);
dcc_release_item(dcc, item, item_pushed);
}
static int handle_migrate_flush_mark(RedChannelClient *rcc)
{
DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base);
@ -1995,7 +1987,6 @@ DisplayChannel* display_channel_new(SpiceServer *reds, RedWorker *worker,
.on_disconnect = on_disconnect,
.send_item = send_item,
.hold_item = hold_item,
.release_item = release_item,
.handle_migrate_flush_mark = handle_migrate_flush_mark,
.handle_migrate_data = handle_migrate_data,
.handle_migrate_data_get_serial = handle_migrate_data_get_serial

View File

@ -241,8 +241,8 @@ static inline int get_stream_id(DisplayChannel *display, Stream *stream)
}
typedef struct RedSurfaceDestroyItem {
SpiceMsgSurfaceDestroy surface_destroy;
RedPipeItem pipe_item;
SpiceMsgSurfaceDestroy surface_destroy;
} RedSurfaceDestroyItem;
typedef struct RedUpgradeItem {

View File

@ -254,12 +254,6 @@ static void inputs_channel_send_migrate_data(RedChannelClient *rcc,
spice_marshaller_add_uint16(m, icc->motion_count);
}
static void inputs_channel_release_pipe_item(RedChannelClient *rcc,
RedPipeItem *base, int item_pushed)
{
free(base);
}
static void inputs_channel_send_item(RedChannelClient *rcc, RedPipeItem *base)
{
SpiceMarshaller *m = red_channel_client_get_marshaller(rcc);
@ -627,7 +621,6 @@ InputsChannel* inputs_channel_new(RedsState *reds)
channel_cbs.on_disconnect = inputs_channel_on_disconnect;
channel_cbs.send_item = inputs_channel_send_item;
channel_cbs.hold_item = inputs_channel_hold_pipe_item;
channel_cbs.release_item = inputs_channel_release_pipe_item;
channel_cbs.alloc_recv_buf = inputs_channel_alloc_msg_rcv_buf;
channel_cbs.release_recv_buf = inputs_channel_release_msg_rcv_buf;
channel_cbs.handle_migrate_data = inputs_channel_handle_migrate_data;

View File

@ -165,9 +165,6 @@ enum NetTestStage {
NET_TEST_STAGE_COMPLETE,
};
static void main_channel_release_pipe_item(RedChannelClient *rcc,
RedPipeItem *base, int item_pushed);
int main_channel_is_connected(MainChannel *main_chan)
{
return red_channel_is_connected(&main_chan->base);
@ -250,13 +247,20 @@ static RedPipeItem *main_agent_tokens_item_new(RedChannelClient *rcc, uint32_t n
return &item->base;
}
static void main_agent_data_item_free(RedAgentDataPipeItem *item)
{
item->free_data(item->data, item->opaque);
free(item);
}
static RedPipeItem *main_agent_data_item_new(RedChannelClient *rcc, uint8_t* data, size_t len,
spice_marshaller_item_free_func free_data,
void *opaque)
{
RedAgentDataPipeItem *item = spice_malloc(sizeof(RedAgentDataPipeItem));
red_pipe_item_init(&item->base, RED_PIPE_ITEM_TYPE_MAIN_AGENT_DATA);
red_pipe_item_init_full(&item->base, RED_PIPE_ITEM_TYPE_MAIN_AGENT_DATA,
(GDestroyNotify)main_agent_data_item_free);
item->data = data;
item->len = len;
item->free_data = free_data;
@ -302,12 +306,19 @@ static RedPipeItem *main_uuid_item_new(MainChannelClient *mcc, const uint8_t uui
return &item->base;
}
static void main_notify_item_free(RedNotifyPipeItem *data)
{
free(data->msg);
free(data);
}
static RedPipeItem *main_notify_item_new(RedChannelClient *rcc, void *data, int num)
{
RedNotifyPipeItem *item = spice_malloc(sizeof(RedNotifyPipeItem));
const char *msg = data;
red_pipe_item_init(&item->base, RED_PIPE_ITEM_TYPE_MAIN_NOTIFY);
red_pipe_item_init_full(&item->base, RED_PIPE_ITEM_TYPE_MAIN_NOTIFY,
(GDestroyNotify)main_notify_item_free);
item->msg = spice_strdup(msg);
return &item->base;
}
@ -712,7 +723,7 @@ static void main_channel_send_item(RedChannelClient *rcc, RedPipeItem *base)
spice_printerr("Init msg for client %p was not sent yet "
"(client is probably during semi-seamless migration). Ignoring msg type %d",
rcc->client, base->type);
main_channel_release_pipe_item(rcc, base, FALSE);
red_pipe_item_unref(base);
return;
}
switch (base->type) {
@ -783,27 +794,6 @@ static void main_channel_send_item(RedChannelClient *rcc, RedPipeItem *base)
red_channel_client_begin_send_message(rcc);
}
static void main_channel_release_pipe_item(RedChannelClient *rcc,
RedPipeItem *base, int item_pushed)
{
switch (base->type) {
case RED_PIPE_ITEM_TYPE_MAIN_AGENT_DATA: {
RedAgentDataPipeItem *data = (RedAgentDataPipeItem *)base;
data->free_data(data->data, data->opaque);
break;
}
case RED_PIPE_ITEM_TYPE_MAIN_NOTIFY: {
RedNotifyPipeItem *data = (RedNotifyPipeItem *)base;
free(data->msg);
break;
}
default:
break;
}
free(base);
}
static void main_channel_client_handle_migrate_connected(MainChannelClient *mcc,
int success,
int seamless)
@ -1165,7 +1155,6 @@ MainChannel* main_channel_new(RedsState *reds)
channel_cbs.on_disconnect = main_channel_client_on_disconnect;
channel_cbs.send_item = main_channel_send_item;
channel_cbs.hold_item = main_channel_hold_pipe_item;
channel_cbs.release_item = main_channel_release_pipe_item;
channel_cbs.alloc_recv_buf = main_channel_alloc_msg_rcv_buf;
channel_cbs.release_recv_buf = main_channel_release_msg_rcv_buf;
channel_cbs.handle_migrate_flush_mark = main_channel_handle_migrate_flush_mark;

View File

@ -578,28 +578,13 @@ static void red_channel_client_send_item(RedChannelClient *rcc, RedPipeItem *ite
rcc->channel->channel_cbs.send_item(rcc, item);
return;
}
free(item);
}
static void red_channel_client_release_item(RedChannelClient *rcc, RedPipeItem *item, int item_pushed)
{
switch (item->type) {
case RED_PIPE_ITEM_TYPE_SET_ACK:
case RED_PIPE_ITEM_TYPE_EMPTY_MSG:
case RED_PIPE_ITEM_TYPE_MIGRATE:
case RED_PIPE_ITEM_TYPE_PING:
free(item);
break;
default:
rcc->channel->channel_cbs.release_item(rcc, item, item_pushed);
}
red_pipe_item_unref(item);
}
static inline void red_channel_client_release_sent_item(RedChannelClient *rcc)
{
if (rcc->send_data.item) {
red_channel_client_release_item(rcc,
rcc->send_data.item, TRUE);
red_pipe_item_unref(rcc->send_data.item);
rcc->send_data.item = NULL;
}
}
@ -1030,7 +1015,7 @@ RedChannel *red_channel_create(int size,
spice_assert(size >= sizeof(*channel));
spice_assert(channel_cbs->config_socket && channel_cbs->on_disconnect && handle_message &&
channel_cbs->alloc_recv_buf && channel_cbs->release_item);
channel_cbs->alloc_recv_buf);
spice_assert(channel_cbs->handle_migrate_data ||
!(migration_flags & SPICE_MIGRATE_NEED_DATA_TRANSFER));
channel = spice_malloc0(size);
@ -1663,7 +1648,7 @@ static inline gboolean client_pipe_add(RedChannelClient *rcc, RedPipeItem *item,
spice_assert(rcc && item);
if (SPICE_UNLIKELY(!red_channel_client_is_connected(rcc))) {
spice_debug("rcc is disconnected %p", rcc);
red_channel_client_release_item(rcc, item, FALSE);
red_pipe_item_unref(item);
return FALSE;
}
if (ring_is_empty(&rcc->pipe) && rcc->stream->watch) {
@ -1770,12 +1755,9 @@ int red_channel_is_connected(RedChannel *channel)
return channel && (channel->clients_num > 0);
}
void red_channel_client_clear_sent_item(RedChannelClient *rcc)
static void red_channel_client_clear_sent_item(RedChannelClient *rcc)
{
if (rcc->send_data.item) {
red_channel_client_release_item(rcc, rcc->send_data.item, TRUE);
rcc->send_data.item = NULL;
}
red_channel_client_release_sent_item(rcc);
rcc->send_data.blocked = FALSE;
rcc->send_data.size = 0;
}
@ -1789,7 +1771,7 @@ void red_channel_client_pipe_clear(RedChannelClient *rcc)
}
while ((item = (RedPipeItem *)ring_get_head(&rcc->pipe))) {
ring_remove(&item->link);
red_channel_client_release_item(rcc, item, FALSE);
red_pipe_item_unref(item);
}
rcc->pipe_size = 0;
}
@ -2033,7 +2015,7 @@ void red_channel_client_pipe_remove_and_release(RedChannelClient *rcc,
RedPipeItem *item)
{
red_channel_client_pipe_remove(rcc, item);
red_channel_client_release_item(rcc, item, FALSE);
red_pipe_item_unref(item);
}
/*
@ -2398,7 +2380,7 @@ int red_channel_client_wait_pipe_item_sent(RedChannelClient *rcc,
red_channel_client_push(rcc);
}
red_channel_client_release_item(rcc, item, TRUE);
red_pipe_item_unref(item);
if (item_in_pipe) {
spice_warning("timeout");
return FALSE;

View File

@ -159,8 +159,6 @@ typedef void (*channel_disconnect_proc)(RedChannelClient *rcc);
typedef int (*channel_configure_socket_proc)(RedChannelClient *rcc);
typedef void (*channel_send_pipe_item_proc)(RedChannelClient *rcc, RedPipeItem *item);
typedef void (*channel_hold_pipe_item_proc)(RedChannelClient *rcc, RedPipeItem *item);
typedef void (*channel_release_pipe_item_proc)(RedChannelClient *rcc,
RedPipeItem *item, int item_pushed);
typedef void (*channel_on_incoming_error_proc)(RedChannelClient *rcc);
typedef void (*channel_on_outgoing_error_proc)(RedChannelClient *rcc);
@ -188,7 +186,6 @@ typedef struct {
channel_disconnect_proc on_disconnect;
channel_send_pipe_item_proc send_item;
channel_hold_pipe_item_proc hold_item;
channel_release_pipe_item_proc release_item;
channel_alloc_msg_recv_buf_proc alloc_recv_buf;
channel_release_msg_recv_buf_proc release_recv_buf;
channel_handle_migrate_flush_mark_proc handle_migrate_flush_mark;

View File

@ -504,16 +504,6 @@ static void smartcard_channel_send_item(RedChannelClient *rcc, RedPipeItem *item
red_channel_client_begin_send_message(rcc);
}
static void smartcard_channel_release_pipe_item(RedChannelClient *rcc,
RedPipeItem *item, int item_pushed)
{
if (item->type == RED_PIPE_ITEM_TYPE_SMARTCARD_DATA) {
red_pipe_item_unref(item);
} else {
free(item);
}
}
static void smartcard_channel_on_disconnect(RedChannelClient *rcc)
{
SmartCardChannelClient *scc = SPICE_CONTAINEROF(rcc, SmartCardChannelClient, base);
@ -541,7 +531,6 @@ static void smartcard_push_error(RedChannelClient *rcc, uint32_t reader_id, VSCE
red_pipe_item_init(&error_item->base, RED_PIPE_ITEM_TYPE_ERROR);
error_item->base.type = RED_PIPE_ITEM_TYPE_ERROR;
error_item->vheader.reader_id = reader_id;
error_item->vheader.type = VSC_Error;
error_item->vheader.length = sizeof(error_item->error);
@ -797,7 +786,6 @@ static void smartcard_init(RedsState *reds)
channel_cbs.on_disconnect = smartcard_channel_on_disconnect;
channel_cbs.send_item = smartcard_channel_send_item;
channel_cbs.hold_item = smartcard_channel_hold_pipe_item;
channel_cbs.release_item = smartcard_channel_release_pipe_item;
channel_cbs.alloc_recv_buf = smartcard_channel_alloc_msg_rcv_buf;
channel_cbs.release_recv_buf = smartcard_channel_release_msg_rcv_buf;
channel_cbs.handle_migrate_flush_mark = smartcard_channel_client_handle_migrate_flush_mark;

View File

@ -431,23 +431,12 @@ static void spicevmc_red_channel_send_item(RedChannelClient *rcc,
break;
default:
spice_error("bad pipe item %d", item->type);
free(item);
red_pipe_item_unref(item);
return;
}
red_channel_client_begin_send_message(rcc);
}
static void spicevmc_red_channel_release_pipe_item(RedChannelClient *rcc,
RedPipeItem *item,
int item_pushed)
{
if (item->type == RED_PIPE_ITEM_TYPE_SPICEVMC_DATA) {
red_pipe_item_unref(item);
} else {
free(item);
}
}
static void spicevmc_connect(RedChannel *channel, RedClient *client,
RedsStream *stream, int migration, int num_common_caps,
uint32_t *common_caps, int num_caps, uint32_t *caps)
@ -509,7 +498,6 @@ RedCharDevice *spicevmc_device_connect(RedsState *reds,
channel_cbs.on_disconnect = spicevmc_red_channel_client_on_disconnect;
channel_cbs.send_item = spicevmc_red_channel_send_item;
channel_cbs.hold_item = spicevmc_red_channel_hold_pipe_item;
channel_cbs.release_item = spicevmc_red_channel_release_pipe_item;
channel_cbs.alloc_recv_buf = spicevmc_red_channel_alloc_msg_rcv_buf;
channel_cbs.release_recv_buf = spicevmc_red_channel_release_msg_rcv_buf;
channel_cbs.handle_migrate_flush_mark = spicevmc_channel_client_handle_migrate_flush_mark;

View File

@ -63,6 +63,36 @@ void stream_agent_stats_print(StreamAgent *agent)
#endif
}
static void stream_create_destroy_item_release(RedPipeItem *base)
{
StreamCreateDestroyItem *item = SPICE_CONTAINEROF(base, StreamCreateDestroyItem, base);
DisplayChannel *display = (DisplayChannel*)item->agent->dcc->common.base.channel;
stream_agent_unref(display, item->agent);
free(item);
}
static RedPipeItem *stream_create_destroy_item_new(StreamAgent *agent, gint type)
{
StreamCreateDestroyItem *item = spice_new0(StreamCreateDestroyItem, 1);
red_pipe_item_init_full(&item->base, type,
(GDestroyNotify)stream_create_destroy_item_release);
agent->stream->refs++;
item->agent = agent;
return &item->base;
}
static RedPipeItem *stream_create_item_new(StreamAgent *agent)
{
return stream_create_destroy_item_new(agent, RED_PIPE_ITEM_TYPE_STREAM_CREATE);
}
static RedPipeItem *stream_destroy_item_new(StreamAgent *agent)
{
return stream_create_destroy_item_new(agent, RED_PIPE_ITEM_TYPE_STREAM_DESTROY);
}
void stream_stop(DisplayChannel *display, Stream *stream)
{
DisplayChannelClient *dcc;
@ -78,7 +108,6 @@ void stream_stop(DisplayChannel *display, Stream *stream)
stream_agent = &dcc->stream_agents[get_stream_id(display, stream)];
region_clear(&stream_agent->vis_region);
region_clear(&stream_agent->clip);
spice_assert(!red_pipe_item_is_linked(&stream_agent->destroy_item));
if (stream_agent->video_encoder && dcc->use_video_encoder_rate_control) {
uint64_t stream_bit_rate = stream_agent->video_encoder->get_bit_rate(stream_agent->video_encoder);
@ -89,8 +118,7 @@ void stream_stop(DisplayChannel *display, Stream *stream)
dcc->streams_max_bit_rate = stream_bit_rate;
}
}
stream->refs++;
red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), &stream_agent->destroy_item);
red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), stream_destroy_item_new(stream_agent));
stream_agent_stats_print(stream_agent);
}
display->streams_size_total -= stream->width * stream->height;
@ -702,7 +730,6 @@ void dcc_create_stream(DisplayChannelClient *dcc, Stream *stream)
spice_return_if_fail(region_is_empty(&agent->vis_region));
stream->refs++;
if (stream->current) {
agent->frames = 1;
region_clone(&agent->vis_region, &stream->current->tree_item.base.rgn);
@ -728,7 +755,7 @@ void dcc_create_stream(DisplayChannelClient *dcc, Stream *stream)
} else {
agent->video_encoder = mjpeg_encoder_new(0, NULL);
}
red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), &agent->create_item);
red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), stream_create_item_new(agent));
if (red_channel_client_test_remote_cap(RED_CHANNEL_CLIENT(dcc), SPICE_DISPLAY_CAP_STREAM_REPORT)) {
RedStreamActivateReportItem *report_pipe_item = spice_malloc0(sizeof(*report_pipe_item));

View File

@ -82,8 +82,6 @@ typedef struct StreamAgent {
vis_region will contain c2 and also the part of c1/c2 that still
displays fragments of the video */
RedPipeItem create_item;
RedPipeItem destroy_item;
Stream *stream;
uint64_t last_send_time;
VideoEncoder *video_encoder;
@ -109,6 +107,11 @@ typedef struct RedStreamClipItem {
RedStreamClipItem * red_stream_clip_item_new (StreamAgent *agent);
typedef struct StreamCreateDestroyItem {
RedPipeItem base;
StreamAgent *agent;
} StreamCreateDestroyItem;
typedef struct ItemTrace {
red_time_t time;
red_time_t first_frame_time;