Design Patterns – How to Design a Buffer for a Console

algorithmsdesigndesign-patternsmultithreadinguml

Problem

I have a graphical console widget that receives output from an interpreter. Unfortunately the console is not fast enough to paint the output in real-time. So I had to implement a buffer(FIFO Thread Safe Queue) that delayed the writes to the console by 5ms. So when normally a loop of 1000 prints would be done in less than 1 ms, it would take 5000ms to print everything.

Sequence diagram for the buffer:

Sequence diagram for a time delayed buffer
sendCode: Send code that the interpreter can compile and run.

writeLine:Write output from the interpreter to the buffer.

startTimer:Starts a timer that times out every 5ms.

getLine:Get the oldest line out of the buffer. Called every 5ms.

line: Line that gets sent to the console where it is displayed.

What I Need

While this strategy of delaying the output works for now, it is not very practical when real-time solutions are needed. I know one other strategy which is to set a buffer size. Then when the buffer size is reached, flush the output. This is a much better strategy since the console will not be choking considering lines are being sent in blocks.

But the problem is that if I set a buffer size of say 50 lines, the user will not see any output until 50 lines have been printed. Reducing the buffer size does not really help either, because then it's meant to reduce stress on the console.

How can I make a buffer system so the output is printed in real-time
while not having the console dying on me.

Best Answer

To add more flesh to the bones of Wikiti's comments.

You need a fixed sized buffer and a timer set to n ms.

  1. When you write code to the buffer, if the buffer was empty, (re-)start the timer to n ms.

  2. If you write to the buffer and it is full then flush it to the console, clear the buffer and stop the timer.

  3. If the timer expires and there is code in the buffer, flush it to the console, clear the buffer and stop the timer.

  4. If the timer expires and there isn't code in the buffer, stop the timer.

This algorithm should be sufficient. It may take a bit of trial and error to get a good balance of buffer size and timer delay to get the smoothest console interaction. You may also find some mileage in making the flush/clear/stop available as a manual flush function though this isn't strictly necessary.