|
wxMaxima
|
The hand-over of Maxima's output from the socket thread to the GUI (GH #2594). More...
#include <wx/string.h>#include <chrono>#include <cstddef>#include <deque>#include <functional>#include <mutex>#include <vector>Go to the source code of this file.
Data Structures | |
| class | MaximaItemQueue |
| Items Maxima sent, on their way from the socket thread to the GUI thread. More... | |
| struct | MaximaItemQueue::Item |
| One piece of Maxima's output: what it is, and its text. More... | |
Enumerations | |
| enum class | DrainResult { Empty , TimeUp , Stopped } |
| Why DrainForAtMost() returned. More... | |
Functions | |
| DrainResult | DrainForAtMost (std::chrono::milliseconds budget, const std::function< bool(MaximaItemQueue::Item &)> &take, const std::function< bool(const MaximaItemQueue::Item &)> &dispatch) |
| Hands items to dispatch() until none is left or the time is used up. | |
| template<class TagMap > | |
| std::size_t | SplitIntoItems (const wxString &buffer, const TagMap &knownTags, int textCause, std::vector< MaximaItemQueue::Item > &items, const std::function< bool()> &stopRequested={}) |
| Splits what Maxima sent into items. | |
The hand-over of Maxima's output from the socket thread to the GUI (GH #2594).
The socket thread splits what Maxima sends into items (one XML tag, or a run of plain text) and the GUI thread works through them. Until GH #2594 every item became a wx event of its own, and wxWidgets handles all pending events before it looks at the keyboard, the mouse or a repaint again. A command that printed faster than wxMaxima could lay the output out, such as for i thru i+1 do disp(i), therefore kept that queue from ever running empty: nothing was drawn, and not even Ctrl+G got through.
So the items now wait in this queue, and the GUI thread takes them one by one, for a limited time per turn of the event loop (DrainForAtMost()). Two more rules keep a flood under control:
|
strong |
Why DrainForAtMost() returned.
| Enumerator | |
|---|---|
| Empty | Nothing left to take. |
| TimeUp | The time was used up and items may be left: come back later. |
| Stopped | dispatch() asked to stop |
| DrainResult DrainForAtMost | ( | std::chrono::milliseconds | budget, |
| const std::function< bool(MaximaItemQueue::Item &)> & | take, | ||
| const std::function< bool(const MaximaItemQueue::Item &)> & | dispatch | ||
| ) |
Hands items to dispatch() until none is left or the time is used up.
Always handles at least one item, so a single item that takes longer than the whole budget can't stall the queue.
| budget | How long to keep dispatching |
| take | Fetches the next item; false if there is none |
| dispatch | Handles one item; false stops the loop (for example because the connection the items came from is gone) |
| std::size_t SplitIntoItems | ( | const wxString & | buffer, |
| const TagMap & | knownTags, | ||
| int | textCause, | ||
| std::vector< MaximaItemQueue::Item > & | items, | ||
| const std::function< bool()> & | stopRequested = {} |
||
| ) |
Splits what Maxima sent into items.
An item is either a complete known XML tag (its start tag, its contents and its end tag), or the plain text between such tags. A newline directly after a tag's end belongs to the tag. A known tag whose end hasn't arrived yet stays in the buffer, as does everything after it – and so does a "<" at the very end that may turn out to start a known tag.
| buffer | What was received, and not handed on yet |
| knownTags | Maps the names of the known tags to the cause their items get |
| textCause | The cause the plain text gets |
| items | Receives the items |
| stopRequested | Ends the split early if it returns true |
buffer were handed onWalks the buffer once. It used to cut each item off the buffer as it found it, copying the whole rest of the buffer each time, which made a buffer full of short items (disp() in a loop, GH #2594) quadratically slow to split.