brings logging component to stable state

This commit is contained in:
tosh 2013-04-17 18:35:10 +02:00
parent 4fa5760162
commit 81cae86559
3 changed files with 69 additions and 33 deletions

View file

@ -19,9 +19,9 @@ namespace {
// anonymous namespace - everything in here only exists within this very .cpp file // anonymous namespace - everything in here only exists within this very .cpp file
// just as 'static' on every effective line in plain C // just as 'static' on every effective line in plain C
unsigned const CHARACTER_BUFFER_SIZE = 16384; unsigned const CHARACTER_BUFFER_SIZE = 16384; // number of character that are buffered
unsigned const LINE_BUFFER_SIZE = 256; unsigned const LINE_BUFFER_SIZE = 256; // number of lines that are buffered
unsigned const MAX_MESSAGE_LENGTH = 512; unsigned const MAX_MESSAGE_LENGTH = 512; // maximum number of characters for a message
bool const TEXT_MONOSPACED = true; bool const TEXT_MONOSPACED = true;
@ -31,7 +31,7 @@ namespace {
// magic constants from the GLUT spec // magic constants from the GLUT spec
// http://www.opengl.org/resources/libraries/glut/spec3/node78.html // http://www.opengl.org/resources/libraries/glut/spec3/node78.html
// ultimately this stuff should be handled in Util?? // ultimately this stuff should be in Util.h??
float const CHAR_UP = 119.05f; float const CHAR_UP = 119.05f;
float const CHAR_DOWN = 33.33f; float const CHAR_DOWN = 33.33f;
float const CHAR_WIDTH = 104.76f; float const CHAR_WIDTH = 104.76f;
@ -82,7 +82,13 @@ inline void Log::addMessage(char const* ptr) {
// precondition: mutex is locked so noone gets in our way // precondition: mutex is locked so noone gets in our way
// T-pipe, if requested
if (_ptrStream != 0l) {
fprintf(_ptrStream, "%s", ptr);
}
while (*ptr != '\0') { while (*ptr != '\0') {
// process the characters
char c = *ptr++; char c = *ptr++;
if (c == '\t') { if (c == '\t') {
@ -98,7 +104,6 @@ inline void Log::addMessage(char const* ptr) {
*_itrWritePos++ = c; *_itrWritePos++ = c;
if (_itrWritePos == _ptrCharsEnd) { if (_itrWritePos == _ptrCharsEnd) {
// reached the end of the circular character buffer? -> start over // reached the end of the circular character buffer? -> start over
_itrWritePos = _arrChars; _itrWritePos = _arrChars;
} }
@ -107,19 +112,28 @@ inline void Log::addMessage(char const* ptr) {
// new line? store its start to the line buffer and mark next line as empty // new line? store its start to the line buffer and mark next line as empty
++_itrLastLine; ++_itrLastLine;
if (_itrLastLine == _ptrLinesEnd) { if (_itrLastLine == _ptrLinesEnd) {
_itrLastLine = _arrLines; _itrLastLine = _arrLines;
_arrLines[1] = 0l;
} else if (_itrLastLine + 1 == _ptrLinesEnd) {
_arrLines[0] = 0l;
} else {
_itrLastLine[1] = 0l; _itrLastLine[1] = 0l;
} else if (_itrLastLine + 1 != _ptrLinesEnd) {
_itrLastLine[1] = 0l;
} else {
_arrLines[0] = 0l;
} }
*_itrLastLine = _itrWriteLineStart; *_itrLastLine = _itrWriteLineStart;
// debug mode: make sure all line pointers we write here are valid
assert(! (_itrLastLine < _arrLines || _itrLastLine >= _ptrLinesEnd));
assert(! (*_itrLastLine < _arrChars || *_itrLastLine >= _ptrCharsEnd));
// terminate line, unless done already // terminate line, unless done already
if (c != '\0') { if (c != '\0') {
*_itrWritePos++ = '\0'; *_itrWritePos++ = '\0';
if (_itrWritePos == _ptrCharsEnd) {
_itrWritePos = _arrChars;
}
} }
// remember start position in character buffer for next line and reset character count // remember start position in character buffer for next line and reset character count
@ -138,12 +152,10 @@ void Log::operator()(char const* fmt, ...) {
// print to buffer // print to buffer
char buf[MAX_MESSAGE_LENGTH]; char buf[MAX_MESSAGE_LENGTH];
if (vsnprintf(buf, MAX_MESSAGE_LENGTH, fmt, args) > 0) { int n = vsnprintf(buf, MAX_MESSAGE_LENGTH, fmt, args);
if (n > 0) {
// all fine? eventually T-pipe to posix file and add message to log // all fine? log the message
if (_ptrStream != 0l) {
fprintf(_ptrStream, "%s", buf);
}
addMessage(buf); addMessage(buf);
} else { } else {
@ -208,6 +220,10 @@ void Log::render(unsigned screenWidth, unsigned screenHeight) {
showLines = n - 1; showLines = n - 1;
break; break;
} }
// debug mode: make sure all line pointers we find here are valid
assert(! (firstLine < _arrLines || firstLine >= _ptrLinesEnd));
assert(! (*firstLine < _arrChars || *firstLine >= _ptrCharsEnd));
} }
// copy the line buffer portion into a contiguous region at _ptrLinesEnd // copy the line buffer portion into a contiguous region at _ptrLinesEnd
@ -222,39 +238,35 @@ void Log::render(unsigned screenWidth, unsigned screenHeight) {
memcpy(_ptrLinesEnd + atEnd, _arrLines, (showLines - atEnd) * sizeof(char*)); memcpy(_ptrLinesEnd + atEnd, _arrLines, (showLines - atEnd) * sizeof(char*));
} }
// copy relevant char buffer portion and determine information to remap the line pointers // copy relevant char buffer portion and determine information to remap the pointers
char* firstChar = *firstLine; char* firstChar = *firstLine;
char* lastChar = *lastLine + strlen(*lastLine) + 1; char* lastChar = *lastLine + strlen(*lastLine) + 1;
ptrdiff_t charOffset = _ptrCharsEnd - firstChar, charOffsetBeforeFirst = 0; ptrdiff_t charOffset = _ptrCharsEnd - firstChar, charOffsetBeforeFirst = 0;
if (firstChar <= lastChar) { if (firstChar <= lastChar) {
memcpy(_ptrCharsEnd, firstChar, lastChar - firstChar); memcpy(_ptrCharsEnd, firstChar, lastChar - firstChar + 1);
} else { } else {
unsigned atEnd = _ptrCharsEnd - firstChar; unsigned atEnd = _ptrCharsEnd - firstChar;
memcpy(_ptrCharsEnd, firstChar, atEnd); memcpy(_ptrCharsEnd, firstChar, atEnd);
memcpy(_ptrCharsEnd + atEnd, _arrChars, lastChar - _arrChars); memcpy(_ptrCharsEnd + atEnd, _arrChars, lastChar + 1 - _arrChars);
charOffsetBeforeFirst = _ptrCharsEnd + atEnd - _arrChars; charOffsetBeforeFirst = _ptrCharsEnd + atEnd - _arrChars;
} }
// get values for rendering // get values for rendering
unsigned logWidth = _valLogWidth; float scaleFactor = _valCharScale;
if (logWidth > screenWidth) {
logWidth = screenWidth;
}
int yStart = int((screenHeight - _valCharYoffset) / _valCharAspect); int yStart = int((screenHeight - _valCharYoffset) / _valCharAspect);
int yStep = int(_valCharHeight / _valCharAspect); int yStep = int(_valCharHeight / _valCharAspect);
float yScale = _valCharAspect; float yScale = _valCharAspect;
pthread_mutex_unlock(& _mtx);
// ok, we got all we need
// render text // render text
char** line = _ptrLinesEnd + showLines; char** line = _ptrLinesEnd + showLines;
int x = screenWidth - _valLogWidth; int x = screenWidth - _valLogWidth;
pthread_mutex_unlock(& _mtx);
// ok, we got all we need
GLint matrixMode; GLint matrixMode;
glGetIntegerv(GL_MATRIX_MODE, & matrixMode); glGetIntegerv(GL_MATRIX_MODE, & matrixMode);
@ -263,17 +275,26 @@ void Log::render(unsigned screenWidth, unsigned screenHeight) {
for (int y = yStart; y > 0; y -= yStep) { for (int y = yStart; y > 0; y -= yStep) {
// debug mode: check line pointer is valid
assert(! (line < _ptrLinesEnd || line >= _ptrLinesEnd + (_ptrLinesEnd - _arrLines)));
// get character pointer // get character pointer
char* chars = *--line; if (--line < _ptrLinesEnd) {
if (! chars) {
break; break;
} }
char* chars = *line;
// debug mode: check char pointer we find is valid
assert(! (chars < _arrChars || chars >= _ptrCharsEnd));
// remap character pointer it to copied buffer // remap character pointer it to copied buffer
chars += chars >= firstChar ? charOffset : charOffsetBeforeFirst; chars += chars >= firstChar ? charOffset : charOffsetBeforeFirst;
// debug mode: check char pointer is still valid (in new range)
assert(! (chars < _ptrCharsEnd || chars >= _ptrCharsEnd + (_ptrCharsEnd - _arrChars)));
// render the string // render the string
drawtext(x, y, _valCharScale, 0.0f, 1.0f, int(TEXT_MONOSPACED), drawtext(x, y, scaleFactor, 0.0f, 1.0f, int(TEXT_MONOSPACED),
chars, TEXT_RED, TEXT_GREEN, TEXT_BLUE); chars, TEXT_RED, TEXT_GREEN, TEXT_BLUE);
//fprintf(stderr, "Log::render, message = \"%s\"\n", chars); //fprintf(stderr, "Log::render, message = \"%s\"\n", chars);
@ -283,5 +304,8 @@ void Log::render(unsigned screenWidth, unsigned screenHeight) {
glMatrixMode(matrixMode); glMatrixMode(matrixMode);
} }
Log printLog;

View file

@ -13,8 +13,17 @@
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <pthread.h> #include <pthread.h>
class Log { class Log;
//
// Call it as you would call 'printf'.
//
extern Log printLog;
//
// Logging subsystem.
//
class Log {
FILE* _ptrStream; FILE* _ptrStream;
char* _arrChars; char* _arrChars;
char* _ptrCharsEnd; char* _ptrCharsEnd;
@ -35,6 +44,7 @@ class Log {
float _valCharAspect; // aspect (h/w) float _valCharAspect; // aspect (h/w)
pthread_mutex_t _mtx; pthread_mutex_t _mtx;
public: public:
explicit Log(FILE* tPipeTo = stdout, unsigned bufferedLines = 1024, explicit Log(FILE* tPipeTo = stdout, unsigned bufferedLines = 1024,
@ -44,14 +54,18 @@ public:
void setLogWidth(unsigned pixels); void setLogWidth(unsigned pixels);
void setCharacterSize(unsigned width, unsigned height); void setCharacterSize(unsigned width, unsigned height);
void operator()(char const* fmt, ...);
void render(unsigned screenWidth, unsigned screenHeight); void render(unsigned screenWidth, unsigned screenHeight);
void operator()(char const* fmt, ...);
private: private:
// don't copy/assign
Log(Log const&); // = delete;
Log& operator=(Log const&); // = delete;
inline void addMessage(char const*); inline void addMessage(char const*);
inline void recalcLineLength();
friend class LogStream; // for optional iostream-style interface that has to be #included separately
}; };
#endif #endif

View file

@ -100,8 +100,6 @@ int fullscreen = 0;
bool wantColorRandomizer = true; // for addSphere and load file bool wantColorRandomizer = true; // for addSphere and load file
Log printLog;
Oscilloscope audioScope(256,200,true); Oscilloscope audioScope(256,200,true);
ViewFrustum viewFrustum; // current state of view frustum, perspective, orientation, etc. ViewFrustum viewFrustum; // current state of view frustum, perspective, orientation, etc.