[Spice-devel] Simple question about channels in spice-gtk

Marc-André Lureau mlureau at redhat.com
Wed Oct 5 04:07:31 PDT 2011


Hi

----- Original Message -----
> 
> Hi,
> With spicec, on client side, each channel is a different thread. I
> know that with the new client this is not true. I would like to know
> how spice-gtk handles the different channels.


Spice-Gtk uses coroutines for all IO. This makes writing async code much easier, as you don't have to deal with continuation data and callbacks and can simply write a function such as.

request_foo (channel) {
   request_data request;
   reply_data reply;

   channel.send_request_foo (request) // this is not blocking
   channel.receive_reply_foo (reply)  // this is not blocking
}

The function will not block the rest of the program, and other channels may be also doing a request simultaneously. The way it works is by using different contexts or stacks for each channels and switching between them when necessary. This is done for you with IO, by switching to the main context loop, and switching back to active channels to let them proceed with the IO when possible. We don't preempt running context, so CPU task will block the rest of the channels, we will probably use threads pools / tasks to have better performances, see notes below.
A thread-per-channel would probably use the same code as above.

But in single-thread model, it is usually involving splitting the function and heap allocation, fragmentation etc..:

request_foo_reply_cb (channel, reply_data, user_data) {
   foo_data *request = user_data;

   // do something with reply

   request.pending.finish ()
   request.delete ()
}

request_foo_sent_cb (channel, user_data) {
   foo_data *request = user_data;

   foo.pending.finished ()

   foo.pending = channel.read_request (request_foo_sent_cb, request)
}

request request_foo (channel) {
   new foo_data *request;

   request.pending = channel.send_request (request_foo_sent_cb, request)

   return request;
}

By avoiding threads, we also avoid using any lock or conditions, which makes programming easier. Of course, nothing comes for free, so it also means you have to be carefull when dealing with context switching. Fortunately, you rarely need to synchronize between channels. There are some cases where attention is needed, but that wouldn't be easier with threads.

Threads and coroutine can be complementary. We may well have a thread per channel if it turns out to be necessary, but I bet it wont be as I) doesn't benefit it. Thread pools for long CPU tasks however are necessary, and we will introduce them soonish probably. There are threads already from various libraries anyway (gstreamer, pulse, glib/gio etc..), so it's not like we can leave without locks etc..

regards


More information about the Spice-devel mailing list