+ sgDebugClass m_logClass;
+ sgDebugPriority m_logPriority;
+ bool m_isRunning;
+ bool m_consoleRequested;
+
+ void startLog()
+ {
+ SGGuard<SGMutex> g(m_lock);
+ if (m_isRunning) return;
+ m_isRunning = true;
+ start();
+ }
+
+ virtual void run()
+ {
+ while (1) {
+ LogEntry entry(m_entries.pop());
+ // special marker entry detected, terminate the thread since we are
+ // making a configuration change or quitting the app
+ if ((entry.debugClass == SG_NONE) && !strcmp(entry.file, "done")) {
+ return;
+ }
+
+ // submit to each installed callback in turn
+ BOOST_FOREACH(simgear::LogCallback* cb, m_callbacks) {
+ (*cb)(entry.debugClass, entry.debugPriority,
+ entry.file, entry.line, entry.message);
+ }
+ } // of main thread loop
+ }
+
+ bool stop()
+ {
+ SGGuard<SGMutex> g(m_lock);
+ if (!m_isRunning) {
+ return false;
+ }
+
+ // log a special marker value, which will cause the thread to wakeup,
+ // and then exit
+ log(SG_NONE, SG_ALERT, "done", -1, "");
+ join();
+
+ m_isRunning = false;
+ return true;
+ }
+
+ void addCallback(simgear::LogCallback* cb)
+ {
+ PauseThread pause(this);
+ m_callbacks.push_back(cb);
+ }
+
+ 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 )
+ {
+ PauseThread pause(this);
+ m_logPriority = p;
+ m_logClass = c;
+ BOOST_FOREACH(simgear::LogCallback* cb, m_consoleCallbacks) {
+ cb->setLogLevels(c, p);
+ }
+ }
+
+ bool would_log( sgDebugClass c, sgDebugPriority p ) const
+ {
+ if (p >= SG_INFO) return true;
+ return ((c & m_logClass) != 0 && p >= m_logPriority);
+ }
+
+ void log( sgDebugClass c, sgDebugPriority p,
+ const char* fileName, int line, const std::string& msg)
+ {
+ LogEntry entry(c, p, fileName, line, msg);
+ m_entries.push(entry);
+ }
+
+ void requestConsole()
+ {
+ PauseThread pause(this);
+ if (m_consoleRequested) {
+ return;
+ }
+
+ m_consoleRequested = true;
+ m_callbacks.push_back(new StderrLogCallback(m_logClass, m_logPriority));
+ m_consoleCallbacks.push_back(m_callbacks.back());
+ }
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+static logstream* global_logstream = NULL;
+static LogStreamPrivate* global_privateLogstream = NULL;
+
+logstream::logstream()
+{
+ global_privateLogstream = new LogStreamPrivate;
+ global_privateLogstream->startLog();