Implement mono_gc_alloc_fixed on Boehm to be uncollectable. This matches SGen behavio...
[mono.git] / mcs / class / referencesource / System / compmod / system / diagnostics / TraceInternal.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="TraceInternal.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>                                                                
5 //------------------------------------------------------------------------------
6
7 namespace System.Diagnostics {
8     using System.Threading;
9     using System.IO;
10     using System.Security.Permissions;
11     using System.Collections;
12
13     internal static class TraceInternal {
14         private static volatile string appName = null;
15         static volatile TraceListenerCollection listeners;
16         static volatile bool autoFlush;
17         static volatile bool useGlobalLock;
18         [ThreadStatic]
19         static int indentLevel;
20         static volatile int indentSize;
21 #if CONFIGURATION_DEP
22         static volatile bool settingsInitialized;
23         static volatile bool defaultInitialized;
24 #endif
25
26
27         // this is internal so TraceSource can use it.  We want to lock on the same object because both TraceInternal and 
28         // TraceSource could be writing to the same listeners at the same time. 
29         internal static readonly object critSec = new object();
30
31         public static TraceListenerCollection Listeners { 
32             get {
33                 InitializeSettings();
34                 if (listeners == null) {
35                     lock (critSec) {
36                         if (listeners == null) {
37                             // We only need to check that the main section exists.  Everything else will get 
38                             // created for us if it doesn't exist already. 
39 #if CONFIGURATION_DEP
40                             SystemDiagnosticsSection configSectionSav = DiagnosticsConfiguration.SystemDiagnosticsSection;
41                             if (configSectionSav != null) {
42                                 listeners = configSectionSav.Trace.Listeners.GetRuntimeObject();
43                             }
44                             else {
45 #endif
46                                 // If machine.config was deleted the code will get to here
47                                 // supply at least something to prevent the world from coming to
48                                 // an abrupt end. 
49                                 listeners = new TraceListenerCollection();
50                                 TraceListener defaultListener = new DefaultTraceListener();
51                                 defaultListener.IndentLevel = indentLevel;
52                                 defaultListener.IndentSize = indentSize;
53                                 listeners.Add(defaultListener);
54 #if CONFIGURATION_DEP
55                             }
56 #endif
57                         }
58                     }
59                 }
60                 return listeners;
61             }
62         }
63
64         internal static string AppName {
65             get {
66                 if (appName == null) {
67 #if FEATURE_MONO_CAS
68                     new EnvironmentPermission(EnvironmentPermissionAccess.Read, "Path").Assert();
69 #endif
70                     appName = Path.GetFileName(Environment.GetCommandLineArgs()[0]);
71                 }
72                 return appName;
73             }
74         }
75         
76         public static bool AutoFlush { 
77             get { 
78                 InitializeSettings();
79                 return autoFlush; 
80             }
81
82             set {
83                 InitializeSettings();    
84                 autoFlush = value;
85             }
86         }
87
88         public static bool UseGlobalLock { 
89             get { 
90                 InitializeSettings();
91                 return useGlobalLock; 
92             }
93
94             set {
95                 InitializeSettings();    
96                 useGlobalLock = value;
97             }
98         }
99         
100         public static int IndentLevel {
101             get { return indentLevel; }
102
103             set {
104                 // Use global lock
105                 lock (critSec) {
106                     // We don't want to throw here -- it is very bad form to have debug or trace
107                     // code throw exceptions!
108                     if (value < 0) {
109                         value = 0;
110                     }
111                     indentLevel = value;
112                     
113                     if (listeners != null) {
114                         foreach (TraceListener listener in Listeners) {
115                             listener.IndentLevel = indentLevel;
116                         }
117                     }
118                 }
119             }
120         }
121
122         public static int IndentSize {
123             get { 
124                 InitializeSettings();
125                 return indentSize; 
126             }
127             
128             set {
129                 InitializeSettings();    
130                 SetIndentSize(value);
131             }
132         }
133
134         static void SetIndentSize(int value) {
135             // Use global lock
136             lock (critSec) {                
137                 // We don't want to throw here -- it is very bad form to have debug or trace
138                 // code throw exceptions!            
139                 if (value < 0) {
140                     value = 0;
141                 }
142
143                 indentSize = value;
144                 
145                 if (listeners != null) {
146                     foreach (TraceListener listener in Listeners) {
147                         listener.IndentSize = indentSize;
148                     }
149                 } 
150             }
151         }
152
153         public static void Indent() {
154             // Use global lock
155             lock (critSec) {
156                 InitializeSettings();
157                 if (indentLevel < Int32.MaxValue) {
158                     indentLevel++;
159                 }
160                 foreach (TraceListener listener in Listeners) {
161                     listener.IndentLevel = indentLevel;
162                 }
163             }
164         }
165
166         public static void Unindent() {
167             // Use global lock
168             lock (critSec) {
169                 InitializeSettings();
170                 if (indentLevel > 0) {
171                     indentLevel--;
172                 }
173                 foreach (TraceListener listener in Listeners) {
174                     listener.IndentLevel = indentLevel;
175                 }
176             }
177         }
178
179         public static void Flush() {
180             if (listeners != null) {
181                 if (UseGlobalLock) {
182                     lock (critSec) {
183                         foreach (TraceListener listener in Listeners) {
184                             listener.Flush();
185                         }            
186                     }
187                 }
188                 else {
189                     foreach (TraceListener listener in Listeners) {
190                         if (!listener.IsThreadSafe) {
191                             lock (listener) {
192                                 listener.Flush();
193                             }
194                         }
195                         else {
196                             listener.Flush();
197                         }
198                     }            
199                 }
200             }
201         }
202
203         public static void Close() {
204             if (listeners != null) {
205                 // Use global lock
206                 lock (critSec) {
207                     foreach (TraceListener listener in Listeners) {
208                         listener.Close();
209                     }            
210                 }
211             }
212         }
213
214         public static void Assert(bool condition) {
215             if (condition) return;
216             Fail(string.Empty);
217         }
218
219         public static void Assert(bool condition, string message) {
220             if (condition) return;
221             Fail(message);
222         }
223
224         public static void Assert(bool condition, string message, string detailMessage) {
225             if (condition) return;
226             Fail(message, detailMessage);
227         }
228
229         public static void Fail(string message) {
230             if (UseGlobalLock) {
231                 lock (critSec) {
232                     foreach (TraceListener listener in Listeners) {
233                         listener.Fail(message);
234                         if (AutoFlush) listener.Flush();
235                     }            
236                 }
237             }
238             else {
239                 foreach (TraceListener listener in Listeners) {
240                     if (!listener.IsThreadSafe) {
241                         lock (listener) {
242                             listener.Fail(message);
243                             if (AutoFlush) listener.Flush();
244                         }
245                     }
246                     else {
247                         listener.Fail(message);
248                         if (AutoFlush) listener.Flush();
249                     }
250                 }            
251             }
252         }        
253
254         public static void Fail(string message, string detailMessage) {
255             if (UseGlobalLock) {
256                 lock (critSec) {
257                     foreach (TraceListener listener in Listeners) {
258                         listener.Fail(message, detailMessage);
259                         if (AutoFlush) listener.Flush();
260                     }            
261                 }
262             }
263             else {
264                 foreach (TraceListener listener in Listeners) {
265                     if (!listener.IsThreadSafe) {
266                         lock (listener) {
267                             listener.Fail(message, detailMessage);
268                             if (AutoFlush) listener.Flush();
269                         }
270                     }
271                     else {
272                         listener.Fail(message, detailMessage);
273                         if (AutoFlush) listener.Flush();
274                     }
275                 }            
276             }
277         }        
278
279         private static void InitializeSettings() {
280 #if CONFIGURATION_DEP
281             // we want to redo this logic exactly once if the last time we entered the config
282             // system was still initializing.  (ASURT 111941, VSWhidbey 149552)
283             if (!settingsInitialized || (defaultInitialized && DiagnosticsConfiguration.IsInitialized())) {
284                 // we should avoid 2 threads altering the state concurrently for predictable behavior
285                 // though it may not be strictly necessary at present
286                 lock(critSec) {
287                     if (!settingsInitialized || (defaultInitialized && DiagnosticsConfiguration.IsInitialized())) {
288                         defaultInitialized = DiagnosticsConfiguration.IsInitializing();
289     
290                         // Getting IndentSize and AutoFlush will load config on demand.
291                         // If we load config and there are trace listeners added, we'll
292                         // end up recursing, but that recursion will be stopped in
293                         // DiagnosticsConfiguration.Initialize()           
294                         SetIndentSize(DiagnosticsConfiguration.IndentSize);
295                         autoFlush = DiagnosticsConfiguration.AutoFlush;
296                         useGlobalLock = DiagnosticsConfiguration.UseGlobalLock;
297                         settingsInitialized = true;
298                     }
299                 }
300             }
301 #endif
302         }
303
304         // This method refreshes all the data from the configuration file, so that updated to the configuration file are mirrored
305         // in the System.Diagnostics.Trace class
306         static internal void Refresh() {
307             lock (critSec) {
308 #if CONFIGURATION_DEP
309                 settingsInitialized = false;
310 #endif
311                 listeners = null;
312             }
313             InitializeSettings();
314         }
315
316         public static void TraceEvent(TraceEventType eventType, int id, string format, params object[] args) {
317
318             TraceEventCache EventCache = new TraceEventCache();
319
320             if (UseGlobalLock) {
321                 lock (critSec) {
322                     if (args == null) {
323                         foreach (TraceListener listener in Listeners) {
324                             listener.TraceEvent(EventCache, AppName, eventType, id, format);
325                             if (AutoFlush) listener.Flush();
326                         }
327                     }
328                     else {
329                         foreach (TraceListener listener in Listeners) {
330                             listener.TraceEvent(EventCache, AppName, eventType, id, format, args);
331                             if (AutoFlush) listener.Flush();
332                         }
333                     }
334                 }
335             }
336             else {
337                 if (args == null) {
338                     foreach (TraceListener listener in Listeners) {
339                         if (!listener.IsThreadSafe) {
340                             lock (listener) {
341                                 listener.TraceEvent(EventCache, AppName, eventType, id, format);
342                                 if (AutoFlush) listener.Flush();
343                             }
344                         }
345                         else {
346                             listener.TraceEvent(EventCache, AppName, eventType, id, format);
347                             if (AutoFlush) listener.Flush();
348                         }
349                     }
350                 }
351                 else {
352                     foreach (TraceListener listener in Listeners) {
353                         if (!listener.IsThreadSafe) {
354                             lock (listener) {
355                                 listener.TraceEvent(EventCache, AppName, eventType, id, format, args);
356                                 if (AutoFlush) listener.Flush();
357                             }
358                         }
359                         else {
360                             listener.TraceEvent(EventCache, AppName, eventType, id, format, args);
361                             if (AutoFlush) listener.Flush();
362                         }
363                     }
364                 }
365             }
366         }
367         
368
369         public static void Write(string message) {
370             if (UseGlobalLock) {
371                 lock (critSec) {
372                     foreach (TraceListener listener in Listeners) {
373                         listener.Write(message);
374                         if (AutoFlush) listener.Flush();
375                     }                        
376                 }
377             }
378             else {
379                 foreach (TraceListener listener in Listeners) {
380                     if (!listener.IsThreadSafe) {
381                         lock (listener) {
382                             listener.Write(message);
383                             if (AutoFlush) listener.Flush();
384                         }
385                     }
386                     else {
387                         listener.Write(message);
388                         if (AutoFlush) listener.Flush();
389                     }
390                 }                        
391             }
392         }
393
394         public static void Write(object value) {
395             if (UseGlobalLock) {
396                 lock (critSec) {
397                     foreach (TraceListener listener in Listeners) {
398                         listener.Write(value);
399                         if (AutoFlush) listener.Flush();
400                     }                        
401                 }
402             }
403             else {
404                 foreach (TraceListener listener in Listeners) {
405                     if (!listener.IsThreadSafe) {
406                         lock (listener) {
407                             listener.Write(value);
408                             if (AutoFlush) listener.Flush();
409                         }
410                     }
411                     else {
412                         listener.Write(value);
413                         if (AutoFlush) listener.Flush();
414                     }
415                 }                        
416             }
417         }
418
419         public static void Write(string message, string category) {
420             if (UseGlobalLock) {
421                 lock (critSec) {
422                     foreach (TraceListener listener in Listeners) {
423                         listener.Write(message, category);
424                         if (AutoFlush) listener.Flush();
425                     }                        
426                 }
427             }
428             else {
429                 foreach (TraceListener listener in Listeners) {
430                     if (!listener.IsThreadSafe) {
431                         lock (listener) {
432                             listener.Write(message, category);
433                             if (AutoFlush) listener.Flush();
434                         }
435                     }
436                     else {
437                         listener.Write(message, category);
438                         if (AutoFlush) listener.Flush();
439                     }
440                 }                        
441             }
442         }
443
444         public static void Write(object value, string category) {
445             if (UseGlobalLock) {
446                 lock (critSec) {
447                     foreach (TraceListener listener in Listeners) {
448                         listener.Write(value, category);
449                         if (AutoFlush) listener.Flush();
450                     }                        
451                 }
452             }
453             else {
454                 foreach (TraceListener listener in Listeners) {
455                     if (!listener.IsThreadSafe) {
456                         lock (listener) {
457                             listener.Write(value, category);
458                             if (AutoFlush) listener.Flush();
459                         }
460                     }
461                     else {
462                         listener.Write(value, category);
463                         if (AutoFlush) listener.Flush();
464                     }
465                 }                        
466             }
467         }
468
469         public static void WriteLine(string message) {
470             if (UseGlobalLock) {
471                 lock (critSec) {
472                     foreach (TraceListener listener in Listeners) {
473                         listener.WriteLine(message);
474                         if (AutoFlush) listener.Flush();
475                     }                        
476                 }
477             }
478             else {
479                 foreach (TraceListener listener in Listeners) {
480                     if (!listener.IsThreadSafe) {
481                         lock (listener) {
482                             listener.WriteLine(message);
483                             if (AutoFlush) listener.Flush();
484                         }
485                     }
486                     else {
487                         listener.WriteLine(message);
488                         if (AutoFlush) listener.Flush();
489                     }
490                 }                        
491             }
492         }
493
494         public static void WriteLine(object value) {
495             if (UseGlobalLock) {
496                 lock (critSec) {
497                     foreach (TraceListener listener in Listeners) {
498                         listener.WriteLine(value);
499                         if (AutoFlush) listener.Flush();
500                     }                        
501                 }
502             }
503             else {
504                 foreach (TraceListener listener in Listeners) {
505                     if (!listener.IsThreadSafe) {
506                         lock (listener) {
507                             listener.WriteLine(value);
508                             if (AutoFlush) listener.Flush();
509                         }
510                     }
511                     else {
512                         listener.WriteLine(value);
513                         if (AutoFlush) listener.Flush();
514                     }
515                 }                        
516             }
517         }
518
519         public static void WriteLine(string message, string category) {
520             if (UseGlobalLock) {
521                 lock (critSec) {
522                     foreach (TraceListener listener in Listeners) {
523                         listener.WriteLine(message, category);
524                         if (AutoFlush) listener.Flush();
525                     }                        
526                 }
527             }
528             else {
529                 foreach (TraceListener listener in Listeners) {
530                     if (!listener.IsThreadSafe) {
531                         lock (listener) {
532                             listener.WriteLine(message, category);
533                             if (AutoFlush) listener.Flush();
534                         }
535                     }
536                     else {
537                         listener.WriteLine(message, category);
538                         if (AutoFlush) listener.Flush();
539                     }
540                 }                        
541             }
542         }
543
544         public static void WriteLine(object value, string category) {
545             if (UseGlobalLock) {
546                 lock (critSec) {
547                     foreach (TraceListener listener in Listeners) {
548                         listener.WriteLine(value, category);
549                         if (AutoFlush) listener.Flush();
550                     }                        
551                 }
552             }
553             else {
554                 foreach (TraceListener listener in Listeners) {
555                     if (!listener.IsThreadSafe) {
556                         lock (listener) {
557                             listener.WriteLine(value, category);
558                             if (AutoFlush) listener.Flush();
559                         }
560                     }
561                     else {
562                         listener.WriteLine(value, category);
563                         if (AutoFlush) listener.Flush();
564                     }
565                 }                        
566             }
567         }
568
569         public static void WriteIf(bool condition, string message) {
570             if (condition)
571                 Write(message);
572         }
573
574         public static void WriteIf(bool condition, object value) {
575             if (condition)
576                 Write(value);
577         }
578
579         public static void WriteIf(bool condition, string message, string category) {
580             if (condition)
581                 Write(message, category);
582         }
583
584         public static void WriteIf(bool condition, object value, string category) {
585             if (condition)
586                 Write(value, category);
587         }
588
589         public static void WriteLineIf(bool condition, string message) {
590             if (condition)
591                 WriteLine(message);
592         }
593
594         public static void WriteLineIf(bool condition, object value) {
595             if (condition)
596                 WriteLine(value);
597         }
598
599         public static void WriteLineIf(bool condition, string message, string category) {
600             if (condition)
601                 WriteLine(message, category);
602         }
603
604         public static void WriteLineIf(bool condition, object value, string category) {
605             if (condition)
606                 WriteLine(value, category);
607         }
608     }
609 }