xref: /aosp_15_r20/external/pigweed/pw_console/internals.rst (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1.. _module-pw_console-internals:
2
3Internal Design
4===============
5.. pigweed-module-subpage::
6   :name: pw_console
7
8Threads and Event Loops
9-----------------------
10
11In `ptpython`_ and `IPython`_ all user repl code is run in the foreground. This
12allows interrupts like ``Ctrl-C`` and functions like ``print()`` and
13``time.sleep()`` to work as expected. Pigweed's Console doesn't use this
14approach as it would hide or freeze the `prompt_toolkit`_ user interface while
15running repl code.
16
17To get around this issue all user repl code is run in a dedicated thread with
18stdout and stderr patched to capture output. This lets the user interface stay
19responsive and new log messages to continue to be displayed.
20
21Here's a diagram showing how ``pw_console`` threads and `asyncio`_ tasks are
22organized.
23
24.. mermaid::
25
26   flowchart LR
27       classDef eventLoop fill:#e3f2fd,stroke:#90caf9,stroke-width:1px;
28       classDef thread fill:#fffde7,stroke:#ffeb3b,stroke-width:1px;
29       classDef plugin fill:#fce4ec,stroke:#f06292,stroke-width:1px;
30       classDef builtinFeature fill:#e0f2f1,stroke:#4db6ac,stroke-width:1px;
31
32       %% Subgraphs are drawn in reverse order.
33
34       subgraph pluginThread [Plugin Thread 1]
35           subgraph pluginLoop [Plugin Event Loop 1]
36               toolbarFunc-->|"Refresh<br/>UI Tokens"| toolbarFunc
37               toolbarFunc[Toolbar Update Function]
38           end
39           class pluginLoop eventLoop;
40       end
41       class pluginThread thread;
42
43       subgraph pluginThread2 [Plugin Thread 2]
44           subgraph pluginLoop2 [Plugin Event Loop 2]
45               paneFunc-->|"Refresh<br/>UI Tokens"| paneFunc
46               paneFunc[Pane Update Function]
47           end
48           class pluginLoop2 eventLoop;
49       end
50       class pluginThread2 thread;
51
52       subgraph replThread [Repl Thread]
53           subgraph replLoop [Repl Event Loop]
54               Task1 -->|Finished| Task2 -->|Cancel with Ctrl-C| Task3
55           end
56           class replLoop eventLoop;
57       end
58       class replThread thread;
59
60       subgraph main [Main Thread]
61           subgraph mainLoop [User Interface Event Loop]
62               log[[Log Pane]]
63               repl[[Python Repl]]
64               pluginToolbar([User Toolbar Plugin])
65               pluginPane([User Pane Plugin])
66               class log,repl builtinFeature;
67               class pluginToolbar,pluginPane plugin;
68           end
69           class mainLoop eventLoop;
70       end
71       class main thread;
72
73       repl-.->|Run Code| replThread
74       pluginToolbar-.->|Register Plugin| pluginThread
75       pluginPane-.->|Register Plugin| pluginThread2
76
77.. _IPython: https://ipython.readthedocs.io/
78.. _prompt_toolkit: https://python-prompt-toolkit.readthedocs.io/
79.. _asyncio: https://docs.python.org/3/library/asyncio.html
80.. _ptpython: https://github.com/prompt-toolkit/ptpython/
81