Elimination of unnecessary terminal flushes

This commit is contained in:
Markus Gans 2020-11-04 16:19:02 +01:00
parent 63672a28d5
commit 1d3522f35b
20 changed files with 170 additions and 114 deletions

View File

@ -1,3 +1,6 @@
2020-11-04 Markus Gans <guru.mail@muenster.de>
* Elimination of unnecessary terminal flushes
2020-11-03 Markus Gans <guru.mail@muenster.de>
* Use FIONREAD to get the number of characters available
for reading on stdin

View File

@ -521,6 +521,9 @@ void MouseDraw::drawCanvas()
}
printarea->has_changes = true;
if ( updateTerminal() )
flush();
}
//----------------------------------------------------------------------

View File

@ -73,6 +73,7 @@ FMouseControl* FApplication::mouse {nullptr}; // mouse control
int FApplication::loop_level {0}; // event loop level
int FApplication::quit_code {EXIT_SUCCESS};
bool FApplication::quit_now {false};
bool FApplication::pending_updates {false};
uInt64 FApplication::next_event_wait {5000}; // 5 ms (200 Hz)
struct timeval FApplication::time_last_event {};
@ -845,7 +846,6 @@ void FApplication::queuingKeyboardInput() const
findKeyboardWidget();
keyboard->escapeKeyHandling(); // special case: Esc key
keyboard->clearKeyBufferOnTimeout();
std::fflush(stdout);
if ( isKeyPressed() )
keyboard->fetchKeyCode();
@ -1234,11 +1234,18 @@ void FApplication::sendWheelEvent ( const FMouseData& md
//----------------------------------------------------------------------
inline void FApplication::flushTerminal()
{
if ( flush_count == 0 || flush_count % 4 != 0 )
if ( ! pending_updates )
return;
if ( flush_count < 4 )
{
flush_count++;
return;
}
flush();
flush_count = 0;
pending_updates = false;
}
//----------------------------------------------------------------------
@ -1321,9 +1328,11 @@ bool FApplication::processNextEvent()
processMouseEvent();
processResizeEvent();
processCloseWidget();
processTerminalUpdate(); // after terminal changes
if ( processTerminalUpdate() ) // after terminal changes
pending_updates = true;
flushTerminal();
flush_count++;
processLogger();
}

View File

@ -270,7 +270,9 @@ void FDialog::setPos (const FPoint& pos, bool)
restoreOverlaidWindows();
FWindow::adjustSize();
setCursorToFocusWidget();
updateTerminal();
if ( updateTerminal() )
flush();
}
//----------------------------------------------------------------------

View File

@ -467,15 +467,13 @@ FKey FKeyboard::UTF8decode (const char utf8[]) const
//----------------------------------------------------------------------
inline ssize_t FKeyboard::readKey()
{
setNonBlockingInput();
int len{0};
if ( ioctl(FTermios::getStdIn(), FIONREAD, &len) >= 0 && len > int(FIFO_BUF_SIZE) )
len = int(FIFO_BUF_SIZE);
else
len = 1;
if ( ioctl(FTermios::getStdIn(), FIONREAD, &len) < 0 || len == 0 )
return 0;
const ssize_t bytes = read(FTermios::getStdIn(), &read_character, std::size_t(len));
setNonBlockingInput();
const ssize_t bytes = read(FTermios::getStdIn(), &read_character, 1);
unsetNonBlockingInput();
return bytes;
}
@ -492,7 +490,7 @@ void FKeyboard::parseKeyBuffer()
if ( bytesread + fifo_offset <= int(FIFO_BUF_SIZE) )
{
fifo_buf[fifo_offset] = char(read_character);
fifo_buf[fifo_offset] = read_character;
fifo_offset++;
fifo_in_use = true;
}
@ -527,8 +525,6 @@ void FKeyboard::parseKeyBuffer()
if ( fkey_queue.size() >= MAX_QUEUE_SIZE )
break;
}
read_character = 0;
}
//----------------------------------------------------------------------

View File

@ -357,7 +357,9 @@ void FLineEdit::onKeyPress (FKeyEvent* ev)
&& key != fc::Fkey_enter )
{
drawInputField();
processTerminalUpdate();
if ( processTerminalUpdate() )
flush();
}
}
@ -397,7 +399,9 @@ void FLineEdit::onMouseDown (FMouseEvent* ev)
adjustTextOffset();
drawInputField();
processTerminalUpdate();
if ( processTerminalUpdate() )
flush();
}
}
@ -431,7 +435,9 @@ void FLineEdit::onMouseMove (FMouseEvent* ev)
adjustTextOffset();
drawInputField();
processTerminalUpdate();
if ( processTerminalUpdate() )
flush();
}
// auto-scrolling when dragging mouse outside the widget
@ -534,7 +540,9 @@ void FLineEdit::onTimer (FTimerEvent*)
adjustTextOffset();
drawInputField();
processTerminalUpdate();
if ( processTerminalUpdate() )
flush();
}
//----------------------------------------------------------------------

View File

@ -352,7 +352,8 @@ void FListBox::onMouseDown (FMouseEvent* ev)
if ( yoffset_before != yoffset )
vbar->drawBar();
processTerminalUpdate();
if ( processTerminalUpdate() )
flush();
}
}
@ -425,8 +426,8 @@ void FListBox::onMouseMove (FMouseEvent* ev)
if ( yoffset_before != yoffset )
vbar->drawBar();
processTerminalUpdate();
flush();
if ( processTerminalUpdate() )
flush();
}
// Auto-scrolling when dragging mouse outside the widget
@ -503,7 +504,8 @@ void FListBox::onTimer (FTimerEvent*)
if ( yoffset_before != yoffset )
vbar->drawBar();
processTerminalUpdate();
if ( processTerminalUpdate() )
flush();
}
//----------------------------------------------------------------------
@ -545,7 +547,8 @@ void FListBox::onWheel (FWheelEvent* ev)
if ( yoffset_before != yoffset )
vbar->drawBar();
processTerminalUpdate();
if ( processTerminalUpdate() )
flush();
}
//----------------------------------------------------------------------
@ -1079,7 +1082,8 @@ inline void FListBox::updateDrawing (bool draw_vbar, bool draw_hbar)
if ( draw_hbar )
hbar->drawBar();
processTerminalUpdate();
if ( processTerminalUpdate() )
flush();
}
//----------------------------------------------------------------------
@ -1799,7 +1803,8 @@ void FListBox::cb_vbarChange (const FWidget*)
if ( yoffset_before != yoffset )
vbar->drawBar();
processTerminalUpdate();
if ( processTerminalUpdate() )
flush();
}
}
@ -1867,7 +1872,8 @@ void FListBox::cb_hbarChange (const FWidget*)
if ( xoffset_before != xoffset )
hbar->drawBar();
processTerminalUpdate();
if ( processTerminalUpdate() )
flush();
}
}

View File

@ -1116,7 +1116,8 @@ void FListView::onMouseDown (FMouseEvent* ev)
if ( first_line_position_before != first_visible_line.getPosition() )
vbar->drawBar();
processTerminalUpdate();
if ( processTerminalUpdate() )
flush();
}
}
}
@ -1220,8 +1221,8 @@ void FListView::onMouseMove (FMouseEvent* ev)
if ( first_line_position_before != first_visible_line.getPosition() )
vbar->drawBar();
processTerminalUpdate();
flush();
if ( processTerminalUpdate() )
flush();
}
// auto-scrolling when dragging mouse outside the widget
@ -1307,7 +1308,8 @@ void FListView::onTimer (FTimerEvent*)
if ( first_line_position_before != first_visible_line.getPosition() )
vbar->drawBar();
processTerminalUpdate();
if ( processTerminalUpdate() )
flush();
}
//----------------------------------------------------------------------
@ -1345,7 +1347,8 @@ void FListView::onWheel (FWheelEvent* ev)
if ( first_line_position_before != first_visible_line.getPosition() )
vbar->drawBar();
processTerminalUpdate();
if ( processTerminalUpdate() )
flush();
}
//----------------------------------------------------------------------
@ -2149,7 +2152,8 @@ void FListView::updateDrawing (bool draw_vbar, bool draw_hbar)
if ( draw_hbar )
hbar->drawBar();
processTerminalUpdate();
if ( processTerminalUpdate() )
flush();
}
//----------------------------------------------------------------------
@ -2868,7 +2872,8 @@ void FListView::cb_vbarChange (const FWidget*)
if ( first_line_position_before != first_visible_line.getPosition() )
vbar->drawBar();
processTerminalUpdate();
if ( processTerminalUpdate() )
flush();
}
}
@ -2933,7 +2938,8 @@ void FListView::cb_hbarChange (const FWidget*)
if ( xoffset_before != xoffset )
hbar->drawBar();
processTerminalUpdate();
if ( processTerminalUpdate() )
flush();
}
}

View File

@ -311,8 +311,9 @@ void FMenu::onMouseMove (FMouseEvent* ev)
else if ( ms.hide_sub_menu )
{
closeOpenedSubMenu();
processTerminalUpdate();
flush();
if ( processTerminalUpdate() )
flush();
}
}

View File

@ -223,8 +223,10 @@ void FMenuBar::onAccel (FAccelEvent* ev)
getStatusBar()->drawMessage();
redraw();
processTerminalUpdate();
flush();
if ( processTerminalUpdate() )
flush();
ev->accept();
}
@ -920,8 +922,9 @@ void FMenuBar::mouseMoveOverList (const FMouseEvent&& ev)
if ( focus_changed )
{
redraw();
processTerminalUpdate();
flush();
if ( processTerminalUpdate() )
flush();
}
}

View File

@ -428,8 +428,9 @@ void FMenuItem::onAccel (FAccelEvent* ev)
mbar->drop_down = false;
}
processTerminalUpdate();
flush();
if ( processTerminalUpdate() )
flush();
ev->accept();
}

View File

@ -144,7 +144,8 @@ void FProgressbar::draw()
if ( getFlags().shadow )
drawShadow(this);
flush();
if ( processTerminalUpdate() )
flush();
}
//----------------------------------------------------------------------

View File

@ -352,7 +352,10 @@ void FScrollbar::onMouseMove (FMouseEvent* ev)
{
setValue(new_val);
drawBar();
processTerminalUpdate();
if ( processTerminalUpdate() )
flush();
processScroll();
}
}
@ -757,7 +760,10 @@ void FScrollbar::jumpToClickPos (int x, int y)
{
setValue(new_val);
drawBar();
processTerminalUpdate();
if ( processTerminalUpdate() )
flush();
scroll_type = FScrollbar::scrollJump;
processScroll();
}

View File

@ -411,7 +411,9 @@ void FScrollView::scrollTo (int x, int y)
viewport->has_changes = true;
copy2area();
processTerminalUpdate();
if ( processTerminalUpdate() )
flush();
}
//----------------------------------------------------------------------

View File

@ -184,7 +184,9 @@ void FTextView::scrollTo (int x, int y)
}
drawText();
processTerminalUpdate();
if ( processTerminalUpdate() )
flush();
}
//----------------------------------------------------------------------
@ -475,7 +477,8 @@ void FTextView::onWheel (FWheelEvent* ev)
if ( isShown() )
drawText();
processTerminalUpdate();
if ( processTerminalUpdate() )
flush();
}
//----------------------------------------------------------------------

View File

@ -62,7 +62,7 @@ uInt FVTerm::clr_bol_length{};
uInt FVTerm::clr_eol_length{};
uInt FVTerm::cursor_address_length{};
struct timeval FVTerm::last_term_size_check{};
std::queue<int>* FVTerm::output_buffer{nullptr};
std::vector<int>* FVTerm::output_buffer{nullptr};
FPoint* FVTerm::term_pos{nullptr};
const FVTerm* FVTerm::init_object{nullptr};
FSystem* FVTerm::fsystem{nullptr};
@ -266,7 +266,7 @@ void FVTerm::putVTerm() const
}
//----------------------------------------------------------------------
void FVTerm::updateTerminal() const
bool FVTerm::updateTerminal() const
{
// Updates pending changes to the terminal
@ -275,7 +275,7 @@ void FVTerm::updateTerminal() const
if ( no_terminal_updates || FApplication::isQuit()
|| ! (hasPendingUpdates(vterm) && draw_completed) )
{
return;
return false;
}
std::size_t changedlines = 0;
@ -287,12 +287,12 @@ void FVTerm::updateTerminal() const
changedlines++;
if ( changedlines % check_interval == 0
&& (keyboard->hasUnprocessedInput() || keyboard->isKeyPressed(0))
&& (keyboard->hasUnprocessedInput() || keyboard->isKeyPressed(0) )
&& skipped_terminal_update <= max_skip )
{
// Skipping terminal updates if there is unprocessed inputs
skipped_terminal_update++;
return;
return false;
}
}
@ -301,6 +301,7 @@ void FVTerm::updateTerminal() const
// sets the new input cursor position
updateTerminalCursor();
return changedlines > 0;
}
//----------------------------------------------------------------------
@ -613,20 +614,18 @@ void FVTerm::flush()
{
// Flush the output buffer
if ( ! output_buffer )
if ( ! output_buffer || output_buffer->empty() )
return;
while ( ! output_buffer->empty() )
{
static const FTerm::defaultPutChar& FTermPutchar = FTerm::putchar();
static const FTerm::defaultPutChar& FTermPutchar = FTerm::putchar();
if ( FTermPutchar )
{
FTermPutchar (output_buffer->front());
output_buffer->pop();
}
}
if ( ! FTermPutchar )
return;
for (auto&& ch : *output_buffer)
FTermPutchar(ch);
output_buffer->clear();
std::fflush(stdout);
}
@ -1263,26 +1262,26 @@ void FVTerm::clearArea (FTermArea* area, int fillchar) const
}
//----------------------------------------------------------------------
void FVTerm::processTerminalUpdate() const
bool FVTerm::processTerminalUpdate() const
{
const auto& data = FTerm::getFTermData();
// Checks if the resizing of the terminal is not finished
if ( data && data->hasTermResized() )
return;
return false;
// Monitor whether the terminal size has changed
if ( isTermSizeChanged() )
{
raise (SIGWINCH); // Send SIGWINCH
return;
return false;
}
// Update data on VTerm
updateVTerm();
// Update the visible terminal
updateTerminal();
return updateTerminal();
}
//----------------------------------------------------------------------
@ -1845,7 +1844,7 @@ void FVTerm::init()
{
fterm = new FTerm();
term_pos = new FPoint(-1, -1);
output_buffer = new std::queue<int>;
output_buffer = new std::vector<int>;
}
catch (const std::bad_alloc&)
{
@ -1857,6 +1856,9 @@ void FVTerm::init()
// The final setting is made later in FTerm::init_locale().
std::setlocale (LC_ALL, "");
// Reserve memory on the terminal output buffer
output_buffer->reserve(TERMINAL_OUTPUT_BUFFER_SIZE + 256);
// term_attribute stores the current state of the terminal
term_attribute.ch = '\0';
term_attribute.fg_color = fc::Default;
@ -3072,23 +3074,17 @@ inline void FVTerm::characterFilter (FChar& next_char)
}
//----------------------------------------------------------------------
inline void FVTerm::appendOutputBuffer (const std::string& s)
inline void FVTerm::appendOutputBuffer (const std::string& str)
{
const auto& c_string = s.c_str();
FTermcap::paddingPrint (c_string, 1, appendOutputBuffer);
}
//----------------------------------------------------------------------
inline void FVTerm::appendOutputBuffer (const char s[])
{
FTermcap::paddingPrint (s, 1, appendOutputBuffer);
for (auto&& ch : str)
FVTerm::appendOutputBuffer(int(ch));
}
//----------------------------------------------------------------------
int FVTerm::appendOutputBuffer (int ch)
{
// append method for unicode character
output_buffer->push(ch);
output_buffer->push_back(ch);
if ( output_buffer->size() >= TERMINAL_OUTPUT_BUFFER_SIZE )
flush();

View File

@ -981,8 +981,10 @@ void FWidget::show()
if ( show_root_widget && show_root_widget == this )
{
finishDrawing();
processTerminalUpdate();
flush();
if ( processTerminalUpdate() )
flush();
show_root_widget = nullptr;
}

View File

@ -243,10 +243,10 @@ class FApplication : public FWidget
int flush_count{0};
static uInt64 next_event_wait;
static timeval time_last_event;
static int loop_level;
static int quit_code;
static bool quit_now;
static int loop_level;
static bool process_timer_event;
static bool pending_updates;
static FMouseControl* mouse;
static FKeyboard* keyboard;
static FWidget* keyboard_widget;

View File

@ -197,7 +197,7 @@ class FKeyboard final
std::queue<FKey> fkey_queue{};
FKey fkey{0};
FKey key{0};
uChar read_character{};
char read_character{};
char fifo_buf[FIFO_BUF_SIZE]{'\0'};
int fifo_offset{0};
int stdin_status_flags{0};

View File

@ -50,7 +50,6 @@
#include <sys/time.h> // need for timeval (cygwin)
#include <queue>
#include <string>
#include <utility>
#include <vector>
@ -255,7 +254,7 @@ class FVTerm
void createVTerm (const FSize&);
void resizeVTerm (const FSize&) const;
void putVTerm() const;
void updateTerminal() const;
bool updateTerminal() const;
virtual void addPreprocessingHandler ( const FVTerm*
, const FPreprocessingFunction& );
virtual void delPreprocessingHandler (const FVTerm*);
@ -318,7 +317,7 @@ class FVTerm
void scrollAreaForward (FTermArea*) const;
void scrollAreaReverse (FTermArea*) const;
void clearArea (FTermArea*, int = ' ') const;
void processTerminalUpdate() const;
bool processTerminalUpdate() const;
static void startDrawing();
static void finishDrawing();
virtual void initTerminal();
@ -420,37 +419,38 @@ class FVTerm
void appendLowerRight (FChar&) const;
static void characterFilter (FChar&);
static void appendOutputBuffer (const std::string&);
static void appendOutputBuffer (const char[]);
template <std::size_t N>
static void appendOutputBuffer (const char (&)[N]);
static int appendOutputBuffer (int);
// Data members
FTermArea* print_area{nullptr}; // print area for this object
FTermArea* child_print_area{nullptr}; // print area for children
FTermArea* vwin{nullptr}; // virtual window
static const FVTerm* init_object; // Global FVTerm object
static FSystem* fsystem;
static FTerm* fterm;
static FTermArea* vterm; // virtual terminal
static FTermArea* vdesktop; // virtual desktop
static FTermArea* active_area; // active area
static std::queue<int>* output_buffer;
static FChar term_attribute;
static FChar next_attribute;
static FChar s_ch; // shadow character
static FChar i_ch; // inherit background character
static FPoint* term_pos; // terminal cursor position
static FKeyboard* keyboard;
static timeval last_term_size_check;
static bool draw_completed;
static bool no_terminal_updates;
static uInt64 term_size_check_timeout;
static int skipped_terminal_update;
static uInt erase_char_length;
static uInt repeat_char_length;
static uInt clr_bol_length;
static uInt clr_eol_length;
static uInt cursor_address_length;
static bool cursor_hideable;
FTermArea* print_area{nullptr}; // print area for this object
FTermArea* child_print_area{nullptr}; // print area for children
FTermArea* vwin{nullptr}; // virtual window
static const FVTerm* init_object; // Global FVTerm object
static FSystem* fsystem;
static FTerm* fterm;
static FTermArea* vterm; // virtual terminal
static FTermArea* vdesktop; // virtual desktop
static FTermArea* active_area; // active area
static std::vector<int>* output_buffer;
static FChar term_attribute;
static FChar next_attribute;
static FChar s_ch; // shadow character
static FChar i_ch; // inherit background character
static FPoint* term_pos; // terminal cursor position
static FKeyboard* keyboard;
static timeval last_term_size_check;
static bool draw_completed;
static bool no_terminal_updates;
static uInt64 term_size_check_timeout;
static int skipped_terminal_update;
static uInt erase_char_length;
static uInt repeat_char_length;
static uInt clr_bol_length;
static uInt clr_eol_length;
static uInt cursor_address_length;
static bool cursor_hideable;
};
@ -988,6 +988,14 @@ inline bool FVTerm::isCursorHideable() const
inline void FVTerm::hideVTermCursor() const
{ vterm->input_cursor_visible = false; }
//----------------------------------------------------------------------
template <std::size_t N>
inline void FVTerm::appendOutputBuffer (const char (&str)[N])
{
for (auto&& ch : str)
FVTerm::appendOutputBuffer(int(ch));
}
} // namespace finalcut
#endif // FVTERM_H