summaryrefslogtreecommitdiff
path: root/docs/spice_threading_model.txt
diff options
context:
space:
mode:
Diffstat (limited to 'docs/spice_threading_model.txt')
-rw-r--r--docs/spice_threading_model.txt80
1 files changed, 80 insertions, 0 deletions
diff --git a/docs/spice_threading_model.txt b/docs/spice_threading_model.txt
new file mode 100644
index 00000000..1101f5d0
--- /dev/null
+++ b/docs/spice_threading_model.txt
@@ -0,0 +1,80 @@
+How does SPICE handle threading
+===============================
+
+Lots of code runs in a single thread.
+
+Qemu usually calls SPICE from its main thread except on callbacks to code
+already running in different threads.
+
+Channels (RedChannel/RedChannelClient code) run mostly on a single
+thread except RedChannels on creation and destruction which MUST be
+done in the main thread.
+Lots of channels run in the main thread but currently CursorChannel and
+DisplayChannel are run from within a thread created by RedWorker.
+Note that different CursorChannel/DisplayChannel (they differ by id) run in
+separate RedWorker threads (currently a single RedWorker thread runs a pair
+of CursorChannel and DisplayChannel).
+
+RedChannelClient runs in the RedChannel thread. Creation is done in the same
+thread while destruction can happen in different threads.
+
+A RedClient instance groups the various RedChannelClient connected to
+the same remote SPICE client.
+These RedChannelClient instances can run in separate threads:
+MainChannelClient and most of the other RedChannelClient will be
+running in the main thread, while the CursorChannelClient and the
+DisplayChannelClient usually will be running from a different thread.
+
+Another important aspect of dealing with multiple threads are the dispatchers.
+Dispatchers are used to send messages/request from one thread to another.
+The main dispatcher is used to send requests to the main thread.
+The Qxl uses a dispatcher to send requests to the RedWorker which will forward
+to DisplayChannel/CursorChannel.
+
+One aspect to take into consideration is the event scheduling. SPICE uses some
+`SpiceCoreInterface` to handle events. As the events will be handled from a
+thread based on the core interface you have to use the correct core. Each
+channel has an associated core interface which can be retrieved using
+`RedChannel::get_core_interface`. There's also a main core interface you can get
+using `reds_get_core_interface`. `reds_core_timer_*` and `reds_core_watch_*`
+functions use the main core interface.
+Even though multiple channel types run in the main thread and so could use
+directly the main code interface, for coherence, rule simplicity and to allows
+the code to be moved in a separate thread easily if needed, it's advisable to
+use the channel core interface (that will be the main core interface in this
+case).
+Currently character devices and not channel code runs in the main thread.
+
+Reference counting and ownership
+--------------------------------
+-> pointer
+
+=> pointer with owning (mostly GObject ref counting)
+
+RedChannelClient::client -> RedClient
+
+RedClient::channels => RedChannelClient
+
+RedClient::mcc -> MainChannelClient
+
+RedChannelClient::channel => RedChannel
+
+RedChannel::clients -> RedChannelClient
+
+The RedClient represents a connection from a remote SPICE client,
+RedClient::channels corresponding to the connections for the individual
+channels. Their lifetime is tied to the TCP connection to this remote client.
+When a disconnection is detected, the corresponding RedChannelClient are
+removed from RedClient::channels and RedChannel::clients (the main owner of
+RedChannelClient is RedClient).
+When MainChannelClient is disconnected, all RedChannelClients connected to the
+same RedClient are automatically disconnected.
+
+Who owns RedClient? RedClient is released when the MainChannelClient attached
+to it is disconnected. In this case a request is scheduled in the main thread
+(even if MainChannelClient runs on the main thread too) and
+reds_client_disconnect is called which calls RedClient::destroy which uses
+RedClient::unref to free the object.
+
+Where is the MainChannelClient freed? On disconnection like other channel
+clients, currently before RedClient which will have a dangling pointer.