1 using System;
  2 using System.Collections;
  3 using System.Threading;
  4 
  5 namespace cmsx.kernel
  6 {
  7     private bool log = false;
  8     private string file;
  9 
 10     public nothrow bool Log()
 11     {
 12         return log;
 13     }
 14 
 15     public nothrow void SetLog()
 16     {
 17         log = true;
 18     }
 19 
 20     public class LogFileWriter
 21     {
 22         static LogFileWriter() : instance(new LogFileWriter())
 23         {
 24         }
 25         public static nothrow LogFileWriter& Instance()
 26         {
 27             return *instance;
 28         }
 29         private LogFileWriter() : writer(System.IO.File.CreateText(file))
 30         {
 31             flusherThread = Thread.StartMethod(Flush);
 32         }
 33         public void Write(const string& msg)
 34         {
 35             writer << msg << endl();
 36         }
 37         public void Exit()
 38         {
 39             exit = true;
 40             exiting.NotifyOne();
 41             flusherThread.Join();
 42         }
 43         private void Flush()
 44         {
 45             try
 46             {
 47                 while (!exit)
 48                 {
 49                     exiting.WaitFor(mtxDuration.FromSeconds(10));
 50                 }
 51             }
 52             catch (const Exception&)
 53             {
 54             }
 55         }
 56         private static UniquePtr<LogFileWriter> instance;
 57         private System.IO.StreamWriter writer;
 58         private Thread flusherThread;
 59         private bool exit;
 60         private RecursiveMutex mtx;
 61         private ConditionVariable exiting;
 62     }
 63 
 64     public nothrow void SetLog(const string& logFile)
 65     {
 66         log = true;
 67         file = logFile;
 68     }
 69 
 70     private TimePoint start;
 71 
 72     public nothrow void StartLog()
 73     {
 74         start = Now();
 75     }
 76 
 77     public nothrow void StopLog()
 78     {
 79         bool logStarted = log && !file.IsEmpty();
 80         if (logStarted)
 81         {
 82             LogFileWriter.Instance().Exit();
 83         }
 84     }
 85 
 86     public class LogLock
 87     {
 88         static LogLock() : instance(new LogLock())
 89         {
 90         }
 91         public static nothrow LogLock& Instance()
 92         {
 93             return *instance;
 94         }
 95         public nothrow Mutex& Mtx()
 96         {
 97             return mtx;
 98         }
 99         private static UniquePtr<LogLock> instance;
100         private Mutex mtx;
101     }
102 
103     public nothrow void LogMessage(const string& methodconst string& msg)
104     {
105         LockGuard<Mutex> lock(LogLock.Instance().Mtx());
106         string m;
107         Duration duration = Now() - start;
108         m.Append(DurationStr(duration)).Append(' ');
109         m.Append(ToString(RtThisThreadId()));
110         m.Append(' ');
111         void* fiberData = OsGetFiberData();
112         Process* process = cast<Process*>(fiberData);
113         if (process == null)
114         {
115             m.Append("kernel");
116         }
117         else
118         {
119             m.Append(ProcessName(process));
120         }
121         m.Append(' ');
122         m.Append(method);
123         m.Append(' ');
124         m.Append(msg);
125         if (file.IsEmpty())
126         {
127             Console.Out() << m << endl();
128         }
129         else
130         {
131             LogFileWriter.Instance().Write(m);
132         }
133     }
134 }