File: server.rst

package info (click to toggle)
xeus-zmq 3.1.2-1
  • links: PTS
  • area: main
  • in suites: forky, sid
  • size: 772 kB
  • sloc: cpp: 4,626; makefile: 157; python: 109
file content (131 lines) | stat: -rw-r--r-- 5,940 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
.. Copyright (c) 2022, Johan Mabille and Sylvain Corlay

   Distributed under the terms of the BSD 3-Clause License.

   The full license is in the file LICENSE, distributed with this software.

Server
======

`xeus-zmq` provides two families of implementations for the `xeus server API`_:

- ``xserver_zmq``, where a single thread polls both the shell and the control channels.
  The default implementation is ``xserver_zmq_default`` and can be instantiated via the
  ``make_xserver_default`` function.
- ``xserver_zmq_split``, where the shell and the control channels have dedicated threads.
  `xeus-zmq` provides two implementations for this family, ``xserver_shell_main`` and
  ``xserver_control_main``, which can be instantiated via the ``make_xserver_shell_main``
  and the ``make_xserver_control_main`` functions respectively.

xserver_zmq_default internals
-----------------------------

The internals of the ``xserver_zmq_default`` class are illustrated in the following diagram:

.. image:: server.svg
   :alt: server

The default server is made of three threads communicating through internal `ZeroMQ` sockets. The main
thread is responsible for polling both ``shell`` and ``controller`` channels. When a message is received
on one of these channels, the corresponding callback is invoked. Any code executed in the interpreter
will be executed by the main thread. If the ``publish`` method is called, the main thread sends a message
to the publisher thread.

Having a dedicated thread for publishing messages makes this operation a non-blocking one. When the kernel's
main thread needs to publish a message, it simply sends it to the publisher thread through an internal socket
and continues its execution. The publisher thread will poll its internal socket and forward the messages to
the ``publisher`` channel.

The last thread is the heartbeat. It is responsible for notifying the client that the kernel is still alive.
This is done by sending messages on the ``heartbeat`` channel at a regular rate.

The main thread is also connected to the publisher and the heartbeat threads through internal ``controller``
channels. These are used to send ``stop`` messages to the subthread and to cleanly stop the kernel.

Extending the default implementation
------------------------------------

The default implementation performs a blocking poll of the channels, which can be a limitation in some
use cases. For instance, you may way want to poll within an event loop to allow asynchronous execution
of code. ``xeus-zmq`` makes it possible to extend the default implementation by inheriting from the
`xserver_zmq class`_. It provides utility methods to poll, read and send messages, so that defining
a new server does not require a lot of code.

``TODO``: link to the xeus-qt example when it has been upgraded to xeus-zmq 2.0

xserver_control_main internals
------------------------------

The ``xserver_control_main`` class is an alternative implementation of the server API, its internals are
illustrated in the following diagram:

.. image:: server_control.svg
   :alt: server_control

This server runs four threads that communicate through internal `ZeroMQ` sockets. The main thread is
responsible for polling the ``control`` channel while a dedicated thread listens on the ``shell``
channel. Having separated threads for the ``control`` and ``shell`` channel makes it possible to send
messages on a channel while the kernel is already processing a message on the other channel. For instance
one can send on the ``control`` channel a request to interrupt a computation running on the ``shell``.

The control thread is also connected to the shell, the publisher and the heartbeat threads through internal
``controller`` channels. Similar to ``xserver_zmq``, these are used to send ``stop`` messages to the
subthread and to stop the kernel in a clean way.

The rest of the implementation is also similar to that of ``xserver_zmq``.

xserver_shell_main internals
----------------------------

The ``xserver_shell_main`` class is almost identical to the ``xserver_control_main`` class, except that
the main thread listens on the ``shell`` channel as illustrated in the following diagram:

.. image:: server_main.svg
   :alt: server_main

Extending xserver_zmq_split
---------------------------

Like the default implementation, the ``xserver_control_main`` and ``xserver_shell_main`` servers
perform a blocking poll on each channel. It is possible to provide a different execution model for
both kinds of servers. However, the process to accomplish this slightly differs from the process of extending
the default implementation. Instead of inheriting from the `xserver_zmq_split class`_, one can provide independent
execution models for the control channel and the shell channel by inheriting from the `xcontrol_runner class`_
and the `xshell_runner class`_ respectively.

.. code::

   // xcustom_runner.hpp

   #include "xeus-zmq/xshell_runner.hpp"

   class xcustom_runner final : public xshell_runner
   {
   public:
      xcustom_runner(event_loop loop);
      ~xcustom_runner() override = default;

   private:
      void run_impl() override;
      event_loop p_loop{ nullptr };
   };


.. code::

   // xcustom_runner.cpp

   # include "xcustom_runner.hpp"

   void xcustom_runner::run_impl()
   {
      // Add custom execution model here
      // Example:
      p_loop->run_forever();
   }

.. _xeus server API: https://xeus.readthedocs.io/en/latest/server.html#public-api
.. _xserver_zmq class: https://github.com/jupyter-xeus/xeus-zmq/blob/main/include/xeus-zmq/xserver_zmq.hpp
.. _xserver_zmq_split class: https://github.com/jupyter-xeus/xeus-zmq/blob/main/include/xeus-zmq/xserver_zmq_split.hpp
.. _xcontrol_runner class: https://github.com/jupyter-xeus/xeus-zmq/blob/main/include/xeus-zmq/xcontrol_runner.hpp
.. _xshell_runner class: https://github.com/jupyter-xeus/xeus-zmq/blob/main/include/xeus-zmq/xshell_runner.hpp