summaryrefslogtreecommitdiff
path: root/docs/architecture.rst
diff options
context:
space:
mode:
Diffstat (limited to 'docs/architecture.rst')
-rw-r--r--docs/architecture.rst97
1 files changed, 37 insertions, 60 deletions
diff --git a/docs/architecture.rst b/docs/architecture.rst
index cfc56f3e..75b70c8a 100644
--- a/docs/architecture.rst
+++ b/docs/architecture.rst
@@ -24,21 +24,20 @@ patterns is received; these callbacks are also referred to as :term:`stream
handlers <stream handler>`. The class also provides a basic eventing system
which can be triggered either manually or on a timed schedule.
-The Main Threads
-~~~~~~~~~~~~~~~~
-:class:`~slixmpp.xmlstream.xmlstream.XMLStream` instances run using at
-least three background threads: the send thread, the read thread, and the
-scheduler thread. The send thread is in charge of monitoring the send queue
-and writing text to the outgoing XML stream. The read thread pulls text off
-of the incoming XML stream and stores the results in an event queue. The
-scheduler thread is used to emit events after a given period of time.
-
-Additionally, the main event processing loop may be executed in its
-own thread if Slixmpp is being used in the background for another
-application.
-
-Short-lived threads may also be spawned as requested for threaded
-:term:`event handlers <event handler>`.
+The event loop
+~~~~~~~~~~~~~~
+:class:`~slixmpp.xmlstream.xmlstream.XMLStream` instances inherit the
+:class:`asyncio.BaseProtocol` class, and therefore do not have to handle
+reads and writes directly, but receive data through
+:meth:`~slixmpp.xmlstream.xmlstream.XMLStream.data_received` and write
+data in the socket transport.
+
+Upon receiving data, :term:`stream handlers <stream handler>` are run
+immediately, except if they are coroutines, in which case they are
+scheduled using :meth:`asyncio.async`.
+
+:term:`Event handlers <event handler>` (which are called inside
+:term:`stream handlers <stream handler>`) work the same way.
How XML Text is Turned into Action
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -53,7 +52,7 @@ when this bit of XML is received (with an assumed namespace of
</message>
-1. **Convert XML strings into objects.**
+#. **Convert XML strings into objects.**
Incoming text is parsed and converted into XML objects (using
ElementTree) which are then wrapped into what are referred to as
@@ -66,65 +65,43 @@ when this bit of XML is received (with an assumed namespace of
``{jabber:client}message`` is associated with the class
:class:`~slixmpp.stanza.Message`.
-2. **Match stanza objects to callbacks.**
+#. **Match stanza objects to callbacks.**
These objects are then compared against the stored patterns associated
- with the registered callback handlers. For each match, a copy of the
- :term:`stanza object` is paired with a reference to the handler and
- placed into the event queue.
-
- Our :class:`~slixmpp.stanza.Message` object is thus paired with the message stanza handler
- :meth:`BaseXMPP._handle_message` to create the tuple::
+ with the registered callback handlers.
- ('stanza', stanza_obj, handler)
+ Each handler matching our :term:`stanza object` is then added to a list.
-3. **Process the event queue.**
+#. **Processing callbacks**
- The event queue is the heart of Slixmpp. Nearly every action that
- takes place is first inserted into this queue, whether that be received
- stanzas, custom events, or scheduled events.
+ Every handler in the list is then called with the :term:`stanza object`
+ as a parameter; if the handler is a
+ :class:`~slixmpp.xmlstream.handler.CoroutineCallback`
+ then it will be scheduled in the event loop using :meth:`asyncio.async`
+ instead of run.
- When the stanza is pulled out of the event queue with an associated
- callback, the callback function is executed with the stanza as its only
- parameter.
-
- .. warning::
- The callback, aka :term:`stream handler`, is executed in the main event
- processing thread. If the handler blocks, event processing will also
- block.
-
-4. **Raise Custom Events**
+#. **Raise Custom Events**
Since a :term:`stream handler` shouldn't block, if extensive processing
for a stanza is required (such as needing to send and receive an
:class:`~slixmpp.stanza.Iq` stanza), then custom events must be used.
These events are not explicitly tied to the incoming XML stream and may
- be raised at any time. Importantly, these events may be handled in their
- own thread.
+ be raised at any time.
- When the event is raised, a copy of the stanza is created for each
- handler registered for the event. In contrast to :term:`stream handlers
- <stream handler>`, these functions are referred to as :term:`event
- handlers <event handler>`. Each stanza/handler pair is then put into the
- event queue.
+ In contrast to :term:`stream handlers <stream handler>`, these functions
+ are referred to as :term:`event handlers <event handler>`.
The code for :meth:`BaseXMPP._handle_message` follows this pattern, and
- raises a ``'message'`` event::
-
- self.event('message', msg)
+ raises a ``'message'`` event
- The event call then places the message object back into the event queue
- paired with an :term:`event handler`::
+ .. code-block:: python
- ('event', 'message', msg_copy1, custom_event_handler_1)
- ('event', 'message', msg_copy2, custom_evetn_handler_2)
+ self.event('message', msg)
-5. **Process Custom Events**
+#. **Process Custom Events**
- The stanza and :term:`event handler` are then pulled from the event
- queue, and the handler is executed, passing the stanza as its only
- argument. If the handler was registered as threaded, then a new thread
- will be spawned for it.
+ The :term:`event handlers <event handler>` are then executed, passing
+ the stanza as the only argument.
.. note::
Events may be raised without needing :term:`stanza objects <stanza object>`.
@@ -135,9 +112,9 @@ when this bit of XML is received (with an assumed namespace of
Finally, after a long trek, our message is handed off to the user's
custom handler in order to do awesome stuff::
- msg.reply()
- msg['body'] = "Hey! This is awesome!"
- msg.send()
+ reply = msg.reply()
+ reply['body'] = "Hey! This is awesome!"
+ reply.send()
.. index:: BaseXMPP, XMLStream