Lots of work on printbuffers
This commit is contained in:
@@ -9,8 +9,8 @@
|
||||
//
|
||||
// Class PrintBuffer is a buffer for storing the output of the print statement.
|
||||
// It is part of the actor tangible. When a lua thread calls 'print', the print
|
||||
// goes into stringstream lthread_console. When the thread stops or yields, the
|
||||
// contents of lthread_console are converted to lines and transferred to the
|
||||
// goes into stringstream lthread_prints. When the thread stops or yields, the
|
||||
// contents of lthread_prints are converted to lines and transferred to the
|
||||
// PrintBuffer of the actor. From there, it gets difference transmitted, and the
|
||||
// client can probe it.
|
||||
//
|
||||
@@ -19,12 +19,12 @@
|
||||
// model and the synchronous model. When the thread finishes, the PrintBuffer
|
||||
// in the actor in the master model will contain this:
|
||||
//
|
||||
// * Block 0: Whose woods these are I think I know. [authoritative]
|
||||
// * Block 1: His house is in the village though; [authoritative]
|
||||
// * Block 2: He will not see me stopping here [authoritative]
|
||||
// * Block 3: To watch his woods fill up with snow. [authoritative]
|
||||
// * Block 4: My little horse must think it queer [authoritative]
|
||||
// * Block 5: To stop without a farmhouse near. [authoritative]
|
||||
// * Line 0: Whose woods these are I think I know. [authoritative]
|
||||
// * Line 1: His house is in the village though; [authoritative]
|
||||
// * Line 2: He will not see me stopping here [authoritative]
|
||||
// * Line 3: To watch his woods fill up with snow. [authoritative]
|
||||
// * Line 4: My little horse must think it queer [authoritative]
|
||||
// * Line 5: To stop without a farmhouse near. [authoritative]
|
||||
//
|
||||
// Note that the buffer stores line numbers, which start from zero the moment
|
||||
// the player logs in. In the master model, all lines are always authoritative
|
||||
@@ -63,6 +63,14 @@
|
||||
// processed. Therefore, the client must be prepared that it might see some
|
||||
// redundant lines for a little while.
|
||||
//
|
||||
// MEMORY EFFICIENCY.
|
||||
//
|
||||
// Every tangible will contain a printbuffer. To avoid memory waste, the
|
||||
// implementation of PrintBuffer stores everything inside a dynamically
|
||||
// allocated "core" struct. All printbuffers that contain nothing share a
|
||||
// common empty core. That way, the empty printbuffers that will exist in 99% of
|
||||
// all tangibles will take up very little space.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -77,66 +85,56 @@
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
|
||||
struct PrintBufferCore;
|
||||
|
||||
class PrintBuffer {
|
||||
private:
|
||||
// The most recent lines printed.
|
||||
std::deque<std::string> lines_;
|
||||
|
||||
// Line number of the first line in the buffer. From this, all other
|
||||
// line numbers can be inferred.
|
||||
int first_line_;
|
||||
|
||||
// Line number of the first unchecked line in the buffer. All line
|
||||
// numbers including this one and beyond are unchecked.
|
||||
int first_unchecked_;
|
||||
|
||||
// The world type of the enclosing model. This is used to determine
|
||||
// whether add_string increments the n_checked counter or not.
|
||||
util::WorldType world_type_;
|
||||
|
||||
// Add a line of text (internal). Line is expected to NOT contain
|
||||
// a newline (or any other weird control characters).
|
||||
void add_line(const char *line, int len);
|
||||
|
||||
|
||||
|
||||
PrintBufferCore *core_;
|
||||
|
||||
public:
|
||||
PrintBuffer(util::WorldType wt);
|
||||
PrintBuffer();
|
||||
~PrintBuffer();
|
||||
|
||||
// Get the current first line.
|
||||
int first_line() const { return first_line_; }
|
||||
|
||||
int first_line() const;
|
||||
|
||||
// Return the line number beyond the end of the buffer.
|
||||
int last_line() const { return first_line_ + int(lines_.size()); }
|
||||
|
||||
int last_line() const;
|
||||
|
||||
// Get the current first unchecked line.
|
||||
int first_unchecked() const { return first_unchecked_; }
|
||||
// Guaranteed to be between first_line and last_line inclusive.
|
||||
int first_unchecked() const;
|
||||
|
||||
// Return true if the printbuffer is in the initial state.
|
||||
// Note: if you clear the buffer, it's back in the initial state.
|
||||
bool never_printed() const;
|
||||
|
||||
// Get the specified line number.
|
||||
const std::string &nth(int n) const { return lines_[n - first_line_]; }
|
||||
const std::string &nth(int n) const;
|
||||
|
||||
// Print the entire contents of the buffer to a string (for unit testing).
|
||||
std::string debug_string() const;
|
||||
|
||||
// Clear the buffer
|
||||
void clear();
|
||||
|
||||
// Add a string. If the string doesn't end in a newline, a newline
|
||||
// is added. The string is broken into lines, and the lines are added
|
||||
// to the PrintBuffer.
|
||||
void add_string(const char *text, int len);
|
||||
void add_string(const std::string &s);
|
||||
void add_string(const std::string &s, bool auth);
|
||||
|
||||
// Discard lines up to but not including line N.
|
||||
void discard_upto(int n);
|
||||
|
||||
// Serialization and deserialization
|
||||
void serialize(StreamBuffer *sb) const;
|
||||
void deserialize(StreamBuffer *sb);
|
||||
|
||||
// Difference transmission
|
||||
void diff(const PrintBuffer &auth, StreamBuffer *sb) const;
|
||||
void patch(StreamBuffer *sb);
|
||||
|
||||
// Clear the buffer (for unit testing)
|
||||
void clear();
|
||||
|
||||
// Print the entire contents of the buffer to a string (for unit testing).
|
||||
std::string debug_string() const;
|
||||
};
|
||||
|
||||
using UniquePrintBuffer = std::unique_ptr<PrintBuffer>;
|
||||
|
||||
class PrintChanneler {
|
||||
private:
|
||||
|
||||
Reference in New Issue
Block a user