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(mtx, Duration.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& method, const 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 }