More pieces to support logging to buffers in the GUI.
sgDebugClass m_class;
sgDebugPriority m_priority;
vector_cstring m_buffer;
+ unsigned int m_stamp;
+ unsigned int m_maxLength;
};
BufferedLogCallback::BufferedLogCallback(sgDebugClass c, sgDebugPriority p) :
{
d->m_class = c;
d->m_priority = p;
+ d->m_stamp = 0;
+ d->m_maxLength = 0xffff;
}
BufferedLogCallback::~BufferedLogCallback()
if ((c & d->m_class) == 0 || p < d->m_priority) return;
- vector_cstring::value_type msg = (vector_cstring::value_type) strdup(aMessage.c_str());
+ vector_cstring::value_type msg;
+ if (aMessage.size() >= d->m_maxLength) {
+ msg = (vector_cstring::value_type) malloc(d->m_maxLength);
+ strncpy((char*) msg, aMessage.c_str(), d->m_maxLength - 1);
+ msg[d->m_maxLength - 1] = 0; // add final NULL byte
+ } else {
+ msg = (vector_cstring::value_type) strdup(aMessage.c_str());
+ }
+
SGGuard<SGMutex> g(d->m_mutex);
d->m_buffer.push_back(msg);
+ d->m_stamp++;
+}
+
+unsigned int BufferedLogCallback::stamp() const
+{
+ return d->m_stamp;
}
-void BufferedLogCallback::threadsafeCopy(vector_cstring& aOutput)
+unsigned int BufferedLogCallback::threadsafeCopy(vector_cstring& aOutput)
{
SGGuard<SGMutex> g(d->m_mutex);
size_t sz = d->m_buffer.size();
aOutput.resize(sz);
memcpy(aOutput.data(), d->m_buffer.data(), sz * sizeof(vector_cstring::value_type));
+ return d->m_stamp;
}
+void BufferedLogCallback::truncateAt(unsigned int t)
+{
+ d->m_maxLength = t;
+}
+
} // of namespace simgear
BufferedLogCallback(sgDebugClass c, sgDebugPriority p);
virtual ~BufferedLogCallback();
+ /// truncate messages longer than a certain length. This is to work-around
+ /// for broken PUI behaviour, it can be removed once PUI is gone.
+ void truncateAt(unsigned int);
+
virtual void operator()(sgDebugClass c, sgDebugPriority p,
const char* file, int line, const std::string& aMessage);
+ /**
+ * read the stamp value associated with the log buffer. This is
+ * incremented whenever the log contents change, so can be used
+ * to poll for changes.
+ */
+ unsigned int stamp() const;
+
/**
* copying a (large) vector of std::string would be very expensive.
* once logged, this call retains storage of the underlying string data,
* copy the buffered log data into the provided output list
* (which will be cleared first). This method is safe to call from
* any thread.
+ *
+ * returns the stamp value of the copied data
*/
- void threadsafeCopy(vector_cstring& aOutput);
+ unsigned int threadsafeCopy(vector_cstring& aOutput);
private:
class BufferedLogCallbackPrivate;
std::auto_ptr<BufferedLogCallbackPrivate> d;
int line;
std::string message;
};
+
+ class PauseThread
+ {
+ public:
+ PauseThread(LogStreamPrivate* parent) : m_parent(parent)
+ {
+ m_wasRunning = m_parent->stop();
+ }
+
+ ~PauseThread()
+ {
+ if (m_wasRunning) {
+ m_parent->startLog();
+ }
+ }
+ private:
+ LogStreamPrivate* m_parent;
+ bool m_wasRunning;
+ };
public:
LogStreamPrivate() :
m_logClass(SG_ALL),
SGMutex m_lock;
SGBlockingQueue<LogEntry> m_entries;
- std::vector<simgear::LogCallback*> m_callbacks;
+
+ typedef std::vector<simgear::LogCallback*> CallbackVec;
+ CallbackVec m_callbacks;
+
sgDebugClass m_logClass;
sgDebugPriority m_logPriority;
bool m_isRunning;
void addCallback(simgear::LogCallback* cb)
{
- bool wasRunning = stop();
+ PauseThread pause(this);
m_callbacks.push_back(cb);
- if (wasRunning) {
- startLog();
+ }
+
+ void removeCallback(simgear::LogCallback* cb)
+ {
+ PauseThread pause(this);
+ CallbackVec::iterator it = std::find(m_callbacks.begin(), m_callbacks.end(), cb);
+ if (it != m_callbacks.end()) {
+ m_callbacks.erase(it);
}
}
void setLogLevels( sgDebugClass c, sgDebugPriority p )
{
- bool wasRunning = stop();
+ PauseThread pause(this);
m_logPriority = p;
m_logClass = c;
m_stderrCallback->setLogLevels(c, p);
- if (wasRunning) {
- startLog();
- }
}
bool would_log( sgDebugClass c, sgDebugPriority p ) const
global_privateLogstream->addCallback(cb);
}
+void
+logstream::removeCallback(simgear::LogCallback* cb)
+{
+ global_privateLogstream->removeCallback(cb);
+}
+
void
logstream::log( sgDebugClass c, sgDebugPriority p,
const char* fileName, int line, const std::string& msg)
* must use appropriate locking.
*/
void addCallback(simgear::LogCallback* cb);
-
- // friend logstream& sglog();
-// static logstream *initGlobalLogstream();
+
+ void removeCallback(simgear::LogCallback* cb);
private:
// constructor