##// END OF EJS Templates
rewritten tracing
cin -
r92:4c0e5ef99986 v2
parent child
Show More
@@ -0,0 +1,15
1 namespace Implab.Diagnostics {
2 public static class Extensions {
3 public static IPromise<T> EndLogicalOperation<T>(this IPromise<T> promise) {
4 Safe.ArgumentNotNull(promise, "promise");
5 var op = TraceContext.Instance.DetachLogicalOperation();
6
7 return promise.Anyway(() => {
8 TraceContext.Instance.EnterLogicalOperation(op,true);
9 TraceLog.EndLogicalOperation();
10 TraceContext.Instance.Leave();
11 });
12 }
13 }
14 }
15
@@ -0,0 +1,24
1 using System;
2
3 namespace Implab.Diagnostics {
4 public class LogEventArgs : EventArgs {
5 public int ThreadId {
6 get;
7 private set;
8 }
9 public LogicalOperation Operation {
10 get;
11 private set;
12 }
13 public int OperationTimeOffset {
14 get;
15 private set;
16 }
17 public LogEventArgs(int threadId, LogicalOperation operation, int timeOffset) {
18 ThreadId = threadId;
19 Operation = operation;
20 OperationTimeOffset = timeOffset;
21 }
22 }
23 }
24
@@ -0,0 +1,13
1 namespace Implab.Diagnostics {
2 public class LogEventArgs<TEvent> : LogEventArgs {
3 public TEvent Value {
4 get;
5 private set;
6 }
7
8 public LogEventArgs(TEvent value, int threadId, LogicalOperation operation, int timeOffset) : base(threadId, operation, timeOffset) {
9 Value = value;
10 }
11 }
12 }
13
@@ -0,0 +1,49
1 namespace Implab.Diagnostics {
2 struct OperationContext {
3 readonly LogicalOperation m_initial;
4 public readonly static OperationContext EMPTY = new OperationContext(LogicalOperation.EMPTY, false);
5 LogicalOperation m_current;
6 readonly bool m_ownership;
7
8 public OperationContext(LogicalOperation operation, bool ownership) {
9 Safe.ArgumentNotNull(operation, "operation");
10
11 m_initial = operation;
12 m_current = operation;
13 m_ownership = ownership;
14 }
15
16 public LogicalOperation CurrentOperation {
17 get { return m_current; }
18 }
19
20 public void BeginLogicalOperation(string name) {
21 m_current = new LogicalOperation(name, m_current);
22 }
23
24 public LogicalOperation DetachLogicalOperation() {
25 var detached = m_current;
26 if (m_current != LogicalOperation.EMPTY) {
27 if (m_current != m_initial)
28 m_current = m_current.Parent;
29 else if (m_ownership)
30 m_current = LogicalOperation.EMPTY;
31 else
32 detached = LogicalOperation.EMPTY;
33 }
34 TraceLog.TraceWarning("EndLogicalOperation can't be applied in the current context");
35 return detached;
36 }
37
38 public void EndLogicalOperation() {
39 if (m_current != m_initial) {
40 m_current = m_current.Parent;
41 } else if (m_current != null && m_ownership) {
42 m_current = null;
43 } else {
44 TraceLog.TraceWarning("EndLogicalOperation can't be applied in the current context");
45 }
46 }
47 }
48 }
49
@@ -1,122 +1,122
1 using Implab.Parallels;
1 using Implab.Parallels;
2 using System;
2 using System;
3 using System.Collections.Generic;
3 using System.Collections.Generic;
4 using System.Linq;
4 using System.Linq;
5 using System.Text;
5 using System.Text;
6 using System.Threading;
6 using System.Threading;
7 using System.Threading.Tasks;
7 using System.Threading.Tasks;
8 using System.Windows.Forms;
8 using System.Windows.Forms;
9
9
10 namespace Implab.Diagnostics.Interactive
10 namespace Implab.Diagnostics.Interactive
11 {
11 {
12 public class InteractiveListener: TextListenerBase
12 public class InteractiveListener: TextListenerBase
13 {
13 {
14 TraceForm m_form;
14 TraceForm m_form;
15
15
16 SynchronizationContext m_syncGuiThread;
16 SynchronizationContext m_syncGuiThread;
17 readonly Promise<object> m_guiStarted = new Promise<object>();
17 readonly Promise<object> m_guiStarted = new Promise<object>();
18
18
19 readonly IPromise m_guiFinished;
19 readonly IPromise m_guiFinished;
20 // readonly IPromise m_workerFinished = new Promise<object>();
20 // readonly IPromise m_workerFinished = new Promise<object>();
21
21
22 readonly MTQueue<TraceViewItem> m_queue = new MTQueue<TraceViewItem>();
22 readonly MTQueue<TraceViewItem> m_queue = new MTQueue<TraceViewItem>();
23 readonly AutoResetEvent m_queueEvent = new AutoResetEvent(false);
23 readonly AutoResetEvent m_queueEvent = new AutoResetEvent(false);
24
24
25 int m_queueLength;
25 int m_queueLength;
26 bool m_exitPending;
26 bool m_exitPending;
27
27
28 readonly object m_pauseLock = new object();
28 readonly object m_pauseLock = new object();
29 bool m_paused;
29 bool m_paused;
30 readonly ManualResetEvent m_pauseEvent = new ManualResetEvent(true);
30 readonly ManualResetEvent m_pauseEvent = new ManualResetEvent(true);
31
31
32 public InteractiveListener(bool global) : base(global) {
32 public InteractiveListener(bool global) : base(global) {
33 m_guiFinished = AsyncPool.InvokeNewThread(GuiThread);
33 m_guiFinished = AsyncPool.InvokeNewThread(GuiThread);
34 /*m_workerFinished = */AsyncPool.InvokeNewThread(QueueThread);
34 /*m_workerFinished = */AsyncPool.InvokeNewThread(QueueThread);
35
35
36 m_guiStarted.Join();
36 m_guiStarted.Join();
37 }
37 }
38
38
39 void GuiThread() {
39 void GuiThread() {
40 m_form = new TraceForm(); // will create SynchronizationContext
40 m_form = new TraceForm(); // will create SynchronizationContext
41
41
42 m_form.PauseEvents += (s,a) => Pause();
42 m_form.PauseEvents += (s,a) => Pause();
43 m_form.ResumeEvents += (s, a) => Resume();
43 m_form.ResumeEvents += (s, a) => Resume();
44
44
45 m_syncGuiThread = SynchronizationContext.Current;
45 m_syncGuiThread = SynchronizationContext.Current;
46 m_guiStarted.Resolve();
46 m_guiStarted.Resolve();
47 Application.Run();
47 Application.Run();
48 }
48 }
49
49
50 void QueueThread() {
50 void QueueThread() {
51 while (!m_exitPending) {
51 while (!m_exitPending) {
52 if (m_paused)
52 if (m_paused)
53 m_pauseEvent.WaitOne();
53 m_pauseEvent.WaitOne();
54
54
55 TraceViewItem item;
55 TraceViewItem item;
56 if (m_queue.TryDequeue(out item)) {
56 if (m_queue.TryDequeue(out item)) {
57 Interlocked.Decrement(ref m_queueLength);
57 Interlocked.Decrement(ref m_queueLength);
58
58
59 m_syncGuiThread.Send(x => m_form.AddTraceEvent(item),null);
59 m_syncGuiThread.Send(x => m_form.AddTraceEvent(item),null);
60 } else {
60 } else {
61 m_queueEvent.WaitOne();
61 m_queueEvent.WaitOne();
62 }
62 }
63 }
63 }
64 }
64 }
65
65
66 public void Pause() {
66 public void Pause() {
67 // for consistency we need to set this properties atomically
67 // for consistency we need to set this properties atomically
68 lock (m_pauseLock) {
68 lock (m_pauseLock) {
69 m_pauseEvent.Reset();
69 m_pauseEvent.Reset();
70 m_paused = true;
70 m_paused = true;
71 }
71 }
72 }
72 }
73
73
74 public void Resume() {
74 public void Resume() {
75 // for consistency we need to set this properties atomically
75 // for consistency we need to set this properties atomically
76 lock (m_pauseLock) {
76 lock (m_pauseLock) {
77 m_paused = false;
77 m_paused = false;
78 m_pauseEvent.Set();
78 m_pauseEvent.Set();
79 }
79 }
80 }
80 }
81
81
82 void Enqueue(TraceViewItem item) {
82 void Enqueue(TraceViewItem item) {
83 m_queue.Enqueue(item);
83 m_queue.Enqueue(item);
84 if (Interlocked.Increment(ref m_queueLength) == 1)
84 if (Interlocked.Increment(ref m_queueLength) == 1)
85 m_queueEvent.Set();
85 m_queueEvent.Set();
86 }
86 }
87
87
88 public void ShowForm() {
88 public void ShowForm() {
89 m_syncGuiThread.Post(x => m_form.Show(), null);
89 m_syncGuiThread.Post(x => m_form.Show(), null);
90 }
90 }
91
91
92 public void HideForm() {
92 public void HideForm() {
93 m_syncGuiThread.Post(x => m_form.Hide(), null);
93 m_syncGuiThread.Post(x => m_form.Hide(), null);
94 }
94 }
95
95
96 void Terminate() {
96 void Terminate() {
97 m_exitPending = true;
97 m_exitPending = true;
98 Resume();
98 Resume();
99 m_syncGuiThread.Post(x => Application.ExitThread(), null);
99 m_syncGuiThread.Post(x => Application.ExitThread(), null);
100 }
100 }
101
101
102 protected override void Dispose(bool disposing) {
102 protected override void Dispose(bool disposing) {
103 if (disposing) {
103 if (disposing) {
104 Terminate();
104 Terminate();
105 m_guiFinished.Join();
105 m_guiFinished.Join();
106 }
106 }
107 base.Dispose(disposing);
107 base.Dispose(disposing);
108 }
108 }
109
109
110 protected override void WriteEntry(TraceContext context, EventText text, string channel) {
110 protected override void WriteEntry(LogEventArgs args, EventText text, string channel) {
111 var item = new TraceViewItem {
111 var item = new TraceViewItem {
112 Indent = text.indent,
112 Indent = text.indent,
113 Message = text.content,
113 Message = text.content,
114 Thread = context.ThreadId,
114 Thread = args.ThreadId,
115 Channel = channel,
115 Channel = channel,
116 Timestamp = Environment.TickCount
116 Timestamp = Environment.TickCount
117 };
117 };
118
118
119 Enqueue(item);
119 Enqueue(item);
120 }
120 }
121 }
121 }
122 }
122 }
@@ -1,34 +1,34
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.Linq;
3 using System.Linq;
4 using System.Text;
4 using System.Text;
5
5
6 namespace Implab.Diagnostics {
6 namespace Implab.Diagnostics {
7 public class ConsoleTraceListener: TextListenerBase {
7 public class ConsoleTraceListener: TextListenerBase {
8
8
9 static readonly object _consoleLock = new object();
9 static readonly object _consoleLock = new object();
10
10
11 public ConsoleTraceListener()
11 public ConsoleTraceListener()
12 : base(true) {
12 : base(true) {
13
13
14 }
14 }
15
15
16 public ConsoleTraceListener(bool global)
16 public ConsoleTraceListener(bool global)
17 : base(global) {
17 : base(global) {
18
18
19 }
19 }
20
20
21 protected override void WriteEntry(TraceContext context, EventText text, string channel) {
21 protected override void WriteEntry(LogEventArgs args, EventText text, string channel) {
22 var msg = new StringBuilder();
22 var msg = new StringBuilder();
23
23
24 for (int i = 0; i < text.indent; i++)
24 for (int i = 0; i < text.indent; i++)
25 msg.Append(" ");
25 msg.Append(" ");
26 msg.AppendFormat("[{0}]:{1}: {2}", context.ThreadId, channel, text.content);
26 msg.AppendFormat("[{0}]:{1}: {2}", args.ThreadId, channel, text.content);
27
27
28 lock (_consoleLock) {
28 lock (_consoleLock) {
29 Console.ForegroundColor = (ConsoleColor)(context.ThreadId % 15 + 1);
29 Console.ForegroundColor = (ConsoleColor)(args.ThreadId % 15 + 1);
30 Console.WriteLine(msg.ToString());
30 Console.WriteLine(msg);
31 }
31 }
32 }
32 }
33 }
33 }
34 }
34 }
@@ -1,10 +1,5
1 using System;
1 namespace Implab.Diagnostics {
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5
6 namespace Implab.Diagnostics {
7 public interface IEventTextFormatter<in TEvent> {
2 public interface IEventTextFormatter<in TEvent> {
8 EventText Format(TraceContext context, TEvent data);
3 EventText Format(LogEventArgs args, TEvent data);
9 }
4 }
10 }
5 }
@@ -1,81 +1,80
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.Linq;
3 using System.Linq;
4 using System.Text;
4 using System.Text;
5
5
6 namespace Implab.Diagnostics {
6 namespace Implab.Diagnostics {
7 /// <summary>
7 /// <summary>
8 /// Канал, Ρ‡Π΅Ρ€Π΅Π· ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΏΡƒΠ±Π»ΠΈΠΊΡƒΡŽΡ‚ΡΡ события ΠΆΡƒΡ€Π½Π°Π»Π°.
8 /// Канал, Ρ‡Π΅Ρ€Π΅Π· ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΏΡƒΠ±Π»ΠΈΠΊΡƒΡŽΡ‚ΡΡ события ΠΆΡƒΡ€Π½Π°Π»Π°.
9 /// </summary>
9 /// </summary>
10 /// <typeparam name="TEvent">Π’ΠΈΠΏ событий Π² ΠΊΠ°Π½Π°Π»Π΅</typeparam>
10 /// <typeparam name="TEvent">Π’ΠΈΠΏ событий Π² ΠΊΠ°Π½Π°Π»Π΅</typeparam>
11 /// <remarks>
11 /// <remarks>
12 /// Бобытиями ΠΆΡƒΡ€Π½Π°Π»Π° ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ Π»ΡŽΠ±Ρ‹Π΅ Ρ‚ΠΈΠΏΡ‹, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ строки, Π² ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΠ΅Ρ€Π΅Π΄Π°Π²Π°Ρ‚ΡŒΡΡ
12 /// Бобытиями ΠΆΡƒΡ€Π½Π°Π»Π° ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ Π»ΡŽΠ±Ρ‹Π΅ Ρ‚ΠΈΠΏΡ‹, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ строки, Π² ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΠ΅Ρ€Π΅Π΄Π°Π²Π°Ρ‚ΡŒΡΡ
13 /// информация, ΠΈΠ»ΠΈ структуры с Π½Π°Π±ΠΎΡ€ΠΎΠΌ ΠΏΠΎΠ»Π΅ΠΉ, ΠΎΠΏΠΈΡΡ‹Π²Π°ΡŽΡ‰ΠΈΡ… Π²Π°ΠΆΠ½ΠΎΡΡ‚ΡŒ, тСкст ΠΈ Π΄Ρ€ΡƒΠ³ΡƒΡŽ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ.
13 /// информация, ΠΈΠ»ΠΈ структуры с Π½Π°Π±ΠΎΡ€ΠΎΠΌ ΠΏΠΎΠ»Π΅ΠΉ, ΠΎΠΏΠΈΡΡ‹Π²Π°ΡŽΡ‰ΠΈΡ… Π²Π°ΠΆΠ½ΠΎΡΡ‚ΡŒ, тСкст ΠΈ Π΄Ρ€ΡƒΠ³ΡƒΡŽ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ.
14 /// </remarks>
14 /// </remarks>
15 public class LogChannel<TEvent> {
15 public class LogChannel<TEvent> {
16 static LogChannel<TEvent> _default = new LogChannel<TEvent>();
16 static LogChannel<TEvent> _default = new LogChannel<TEvent>();
17
17
18 /// <summary>
18 /// <summary>
19 /// Канал ΠΏΠΎ-ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ для событий Ρ‚ΠΈΠΏΠ° <typeparam name="TEvent"/>.
19 /// Канал ΠΏΠΎ-ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ для событий Ρ‚ΠΈΠΏΠ° <typeparam name="TEvent"/>.
20 /// </summary>
20 /// </summary>
21 public static LogChannel<TEvent> Default {
21 public static LogChannel<TEvent> Default {
22 get {
22 get {
23 return _default;
23 return _default;
24 }
24 }
25 }
25 }
26
26
27 /// <summary>
27 /// <summary>
28 /// Π‘ΠΎΠ±Ρ‹Ρ‚ΠΈΠ΅ появлСниС Π½ΠΎΠ²ΠΎΠΉ записи Π² ΠΆΡƒΡ€Π½Π°Π»Π΅, Π½Π° это событиС ΠΏΠΎΠ΄ΠΏΠΈΡΡ‹Π²Π°ΡŽΡ‚ΡΡ ΡΠ»ΡƒΡˆΠ°Ρ‚Π΅Π»ΠΈ.
28 /// Π‘ΠΎΠ±Ρ‹Ρ‚ΠΈΠ΅ появлСниС Π½ΠΎΠ²ΠΎΠΉ записи Π² ΠΆΡƒΡ€Π½Π°Π»Π΅, Π½Π° это событиС ΠΏΠΎΠ΄ΠΏΠΈΡΡ‹Π²Π°ΡŽΡ‚ΡΡ ΡΠ»ΡƒΡˆΠ°Ρ‚Π΅Π»ΠΈ.
29 /// </summary>
29 /// </summary>
30 public event EventHandler<ValueEventArgs<TEvent>> Events;
30 public event EventHandler<LogEventArgs<TEvent>> Events;
31
31
32 /// <summary>
32 /// <summary>
33 /// Имя ΠΊΠ°Π½Π°Π»Π°, ΠΏΠΎΠ»Π΅Π·Π½ΠΎ для отобраТСния Π² ΠΆΡƒΡ€Π½Π°Π»Π΅
33 /// Имя ΠΊΠ°Π½Π°Π»Π°, ΠΏΠΎΠ»Π΅Π·Π½ΠΎ для отобраТСния Π² ΠΆΡƒΡ€Π½Π°Π»Π΅
34 /// </summary>
34 /// </summary>
35 public string Name {
35 public string Name {
36 get;
36 get;
37 private set;
37 private set;
38 }
38 }
39
39
40 /// <summary>
40 /// <summary>
41 /// Π‘ΠΎΠ·Π΄Π°Π΅Ρ‚ ΠΆΡƒΡ€Π½Π°Π», имя Ρ‚ΠΈΠΏΠ° событий назначаСтся Π² ΠΊΠ°Ρ‡Π΅Ρ‚Π²Π΅ ΠΈΠΌΠ΅Π½ΠΈ ΠΊΠ°Π½Π°Π»Π°.
41 /// Π‘ΠΎΠ·Π΄Π°Π΅Ρ‚ ΠΆΡƒΡ€Π½Π°Π», имя Ρ‚ΠΈΠΏΠ° событий назначаСтся Π² ΠΊΠ°Ρ‡Π΅Ρ‚Π²Π΅ ΠΈΠΌΠ΅Π½ΠΈ ΠΊΠ°Π½Π°Π»Π°.
42 /// </summary>
42 /// </summary>
43 public LogChannel()
43 public LogChannel()
44 : this(null) {
44 : this(null) {
45 }
45 }
46
46
47 /// <summary>
47 /// <summary>
48 /// Π‘ΠΎΠ΄Π°Π΅Ρ‚ ΠΊΠ°Π½Π°Π» с ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹ΠΌ ΠΈΠΌΠ΅Π½Π΅ΠΌ.
48 /// Π‘ΠΎΠ΄Π°Π΅Ρ‚ ΠΊΠ°Π½Π°Π» с ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹ΠΌ ΠΈΠΌΠ΅Π½Π΅ΠΌ.
49 /// </summary>
49 /// </summary>
50 /// <param name="name">Имя канала.</param>
50 /// <param name="name">Имя канала.</param>
51 public LogChannel(string name) {
51 public LogChannel(string name) {
52 if (String.IsNullOrEmpty(name))
52 if (String.IsNullOrEmpty(name))
53 name = typeof(TEvent).Name;
53 name = typeof(TEvent).Name;
54 Name = name;
54 Name = name;
55 }
55 }
56
56
57 /// <summary>
57 /// <summary>
58 /// ΠžΡ‚ΠΏΡ€Π°Π²Π»ΡΠ΅Ρ‚ запись ΠΆΡƒΡ€Π½Π°Π»Π° Ρ‡Π΅Ρ€Π΅Π· ΠΊΠ°Π½Π°Π» подписчикам.
58 /// ΠžΡ‚ΠΏΡ€Π°Π²Π»ΡΠ΅Ρ‚ запись ΠΆΡƒΡ€Π½Π°Π»Π° Ρ‡Π΅Ρ€Π΅Π· ΠΊΠ°Π½Π°Π» подписчикам.
59 /// </summary>
59 /// </summary>
60 /// <param name="data">Π—Π°ΠΏΠΈΡΡŒ ΠΆΡƒΡ€Π½Π°Π»Π°.</param>
60 /// <param name="data">Π—Π°ΠΏΠΈΡΡŒ ΠΆΡƒΡ€Π½Π°Π»Π°.</param>
61 /// <remarks>
61 /// <remarks>
62 /// ΠšΠΎΠ½Ρ‚Π΅ΠΊΡΡ‚ трассировки ΠΎΡ‚ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ рассылаСтся сообщСниС опрСдСляСтся автоматичСски ΠΈΠ· Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π³ΠΎ ΠΏΠΎΡ‚ΠΎΠΊΠ°.
62 /// ΠšΠΎΠ½Ρ‚Π΅ΠΊΡΡ‚ трассировки ΠΎΡ‚ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ рассылаСтся сообщСниС опрСдСляСтся автоматичСски ΠΈΠ· Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π³ΠΎ ΠΏΠΎΡ‚ΠΎΠΊΠ°.
63 /// </remarks>
63 /// </remarks>
64 public void LogEvent(TEvent data) {
64 public void LogEvent(TEvent data) {
65 var t = Events;
65 var t = Events;
66 if (t!= null)
66 if (t != null) {
67 t(TraceContext.Current,new ValueEventArgs<TEvent>(data));
67 var traceContext = TraceContext.Instance;
68 }
68 t(
69
69 this,
70 /// <summary>
70 new LogEventArgs<TEvent>(
71 /// ΠžΡ‚ΠΏΡ€Π°Π²Π»ΡΠ΅Ρ‚ запись ΠΆΡƒΡ€Π½Π°Π»Π° Ρ‡Π΅Ρ€Π΅Π· ΠΊΠ°Π½Π°Π» подписчикам.
71 data,
72 /// </summary>
72 traceContext.ThreadId,
73 /// <param name="data">Π—Π°ΠΏΠΈΡΡŒ ΠΆΡƒΡ€Π½Π°Π»Π°.</param>
73 traceContext.CurrentOperation,
74 /// <param name="context">ΠšΠΎΠ½Ρ‚Π΅ΠΊΡΡ‚ трассировки ΠΎΡ‚ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ рассылаСтся сообщСниС/</param>
74 traceContext.CurrentOperation.Duration
75 public void LogEvent(TraceContext context,TEvent data) {
75 )
76 var t = Events;
76 );
77 if (t != null)
77 }
78 t(context, new ValueEventArgs<TEvent>(data));
79 }
78 }
80 }
79 }
81 }
80 }
@@ -1,47 +1,45
1 using System;
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6
2
7 namespace Implab.Diagnostics {
3 namespace Implab.Diagnostics {
8 public class LogicalOperation {
4 public class LogicalOperation {
5 public static readonly LogicalOperation EMPTY = new LogicalOperation("__EMPTY__", null);
6
9 readonly LogicalOperation m_parent;
7 readonly LogicalOperation m_parent;
10 readonly string m_name;
8 readonly string m_name;
11 readonly int m_level;
9 readonly int m_level;
12 readonly int m_timestamp;
10 readonly int m_timestamp;
13
11
14 public LogicalOperation()
12 public LogicalOperation()
15 : this(null, null) {
13 : this(null, null) {
16 }
14 }
17
15
18 public LogicalOperation(string name, LogicalOperation parent) {
16 public LogicalOperation(string name, LogicalOperation parent) {
19 m_name = name ?? String.Empty;
17 m_name = name ?? String.Empty;
20 m_parent = parent;
18 m_parent = parent;
21
19
22 m_level = parent == null ? 0 : parent.Level + 1;
20 m_level = parent == null ? 0 : parent.Level + 1;
23 m_timestamp = Environment.TickCount;
21 m_timestamp = Environment.TickCount;
24 }
22 }
25
23
26 public int Duration {
24 public int Duration {
27 get {
25 get {
28 var dt = Environment.TickCount - m_timestamp;
26 var dt = Environment.TickCount - m_timestamp;
29 return dt < 0 ? int.MaxValue + dt : dt; // handle overflow
27 return dt < 0 ? int.MaxValue + dt : dt; // handle overflow
30 }
28 }
31 }
29 }
32
30
33 public LogicalOperation Parent {
31 public LogicalOperation Parent {
34 get {
32 get {
35 return m_parent;
33 return m_parent;
36 }
34 }
37 }
35 }
38
36
39 public int Level {
37 public int Level {
40 get { return m_level; }
38 get { return m_level; }
41 }
39 }
42
40
43 public string Name {
41 public string Name {
44 get { return m_name; }
42 get { return m_name; }
45 }
43 }
46 }
44 }
47 }
45 }
@@ -1,47 +1,45
1 using System;
1 using System;
2 using System.Collections.Generic;
3 using System.IO;
2 using System.IO;
4 using System.Linq;
5 using System.Text;
3 using System.Text;
6
4
7 namespace Implab.Diagnostics {
5 namespace Implab.Diagnostics {
8 public class TextFileListener: TextListenerBase {
6 public class TextFileListener: TextListenerBase {
9 readonly TextWriter m_textWriter;
7 readonly TextWriter m_textWriter;
10
8
11 public TextFileListener(string fileName, bool global)
9 public TextFileListener(string fileName, bool global)
12 : base(global) {
10 : base(global) {
13 m_textWriter = File.CreateText(fileName);
11 m_textWriter = File.CreateText(fileName);
14
12
15 m_textWriter.WriteLine("LOG {0}", DateTime.Now);
13 m_textWriter.WriteLine("LOG {0}", DateTime.Now);
16 Register(this);
14 Register(this);
17 }
15 }
18
16
19 protected override void WriteEntry(TraceContext context, EventText text, string channel) {
17 protected override void WriteEntry(LogEventArgs args, EventText text, string channel) {
20 var msg = new StringBuilder();
18 var msg = new StringBuilder();
21 for (int i = 0; i < text.indent; i++)
19 for (int i = 0; i < text.indent; i++)
22 msg.Append(" ");
20 msg.Append(" ");
23 msg.AppendFormat("[{0}]:{1}: {2}", context.ThreadId, channel, text.content);
21 msg.AppendFormat("[{0}]:{1}: {2}", args.ThreadId, channel, text.content);
24
22
25 lock (m_textWriter) {
23 lock (m_textWriter) {
26 if (!IsDisposed) {
24 if (!IsDisposed) {
27 // Ρ‚ΡƒΡ‚ Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½ΠΎ Π΅Ρ‰Π΅ Π½Π΅ освобоТдСн m_textWriter
25 // Ρ‚ΡƒΡ‚ Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½ΠΎ Π΅Ρ‰Π΅ Π½Π΅ освобоТдСн m_textWriter
28 m_textWriter.WriteLine(msg.ToString());
26 m_textWriter.WriteLine(msg);
29 m_textWriter.Flush();
27 m_textWriter.Flush();
30 }
28 }
31 }
29 }
32 }
30 }
33
31
34
32
35 protected override void Dispose(bool disposing) {
33 protected override void Dispose(bool disposing) {
36 base.Dispose(disposing);
34 base.Dispose(disposing);
37 if (disposing) {
35 if (disposing) {
38 // IsDisposed = true
36 // IsDisposed = true
39 lock (m_textWriter) {
37 lock (m_textWriter) {
40 Safe.Dispose(m_textWriter);
38 Safe.Dispose(m_textWriter);
41 }
39 }
42 }
40 }
43 }
41 }
44
42
45
43
46 }
44 }
47 }
45 }
@@ -1,129 +1,128
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.Linq;
3 using System.Linq;
4 using System.Text;
4 using System.Text;
5
5
6 namespace Implab.Diagnostics {
6 namespace Implab.Diagnostics {
7 public abstract class TextListenerBase : ServiceLocator, IEventTextFormatter<object>, IEventTextFormatter<TraceEvent> {
7 public abstract class TextListenerBase : ServiceLocator, IEventTextFormatter<object>, IEventTextFormatter<TraceEvent> {
8
8
9 readonly Dictionary<object, Action> m_subscriptions = new Dictionary<object, Action>();
9 readonly Dictionary<object, Action> m_subscriptions = new Dictionary<object, Action>();
10 readonly LogicalOperation m_boundOperation;
10 readonly LogicalOperation m_boundOperation;
11 readonly int m_baseIndent;
11 readonly int m_baseIndent;
12
12
13 protected TextListenerBase(bool global) {
13 protected TextListenerBase(bool global) {
14 Register(this);
14 Register(this);
15 if (!global) {
15 if (!global) {
16 m_boundOperation = TraceContext.Current.CurrentOperation;
16 m_boundOperation = TraceContext.Instance.CurrentOperation;
17 m_baseIndent = Math.Max(0, m_boundOperation.Level - 1);
17 m_baseIndent = Math.Max(0, m_boundOperation.Level - 1);
18 }
18 }
19 }
19 }
20
20
21 public void Subscribe(Type eventType) {
21 public void Subscribe(Type eventType) {
22 if (eventType == null)
22 if (eventType == null)
23 throw new ArgumentNullException("eventType");
23 throw new ArgumentNullException("eventType");
24 GetType().GetMethod("Subscribe", new Type[0]).MakeGenericMethod(eventType).Invoke(this, null);
24 GetType().GetMethod("Subscribe", new Type[0]).MakeGenericMethod(eventType).Invoke(this, null);
25 }
25 }
26
26
27 public void Subscribe<TEvent>() {
27 public void Subscribe<TEvent>() {
28 Subscribe<TEvent>(LogChannel<TEvent>.Default);
28 Subscribe<TEvent>(LogChannel<TEvent>.Default);
29 }
29 }
30
30
31 public void Subscribe<TEvent>(LogChannel<TEvent> channel) {
31 public void Subscribe<TEvent>(LogChannel<TEvent> channel) {
32 if (channel == null)
32 if (channel == null)
33 throw new ArgumentNullException("channel");
33 throw new ArgumentNullException("channel");
34
34
35 lock (m_subscriptions) {
35 lock (m_subscriptions) {
36 AssertNotDisposed();
36 AssertNotDisposed();
37
37
38 var formatter = GetService<IEventTextFormatter<TEvent>>();
38 var formatter = GetService<IEventTextFormatter<TEvent>>();
39 var channelName = channel.Name;
39 var channelName = channel.Name;
40
40
41 EventHandler<ValueEventArgs<TEvent>> handler = (sender, args) => {
41 EventHandler<LogEventArgs<TEvent>> handler = (sender, args) => {
42 TraceContext context = (TraceContext)sender;
42 var text = formatter.Format(args, args.Value);
43 var text = formatter.Format(context, args.Value);
44 text.indent -= m_baseIndent;
43 text.indent -= m_baseIndent;
45
44
46 if (IsRelated(context.CurrentOperation))
45 if (IsRelated(args.Operation))
47 WriteEntry(context, text, channelName);
46 WriteEntry(args, text, channelName);
48 };
47 };
49
48
50 if (m_subscriptions.ContainsKey(channel))
49 if (m_subscriptions.ContainsKey(channel))
51 return;
50 return;
52
51
53 channel.Events += handler;
52 channel.Events += handler;
54
53
55 Action unsubscribe = () => {
54 Action unsubscribe = () => {
56 channel.Events -= handler;
55 channel.Events -= handler;
57 };
56 };
58
57
59 m_subscriptions.Add(channel, unsubscribe);
58 m_subscriptions.Add(channel, unsubscribe);
60 }
59 }
61 }
60 }
62
61
63 public bool IsRelated(LogicalOperation op) {
62 public bool IsRelated(LogicalOperation op) {
64 if (m_boundOperation == null)
63 if (m_boundOperation == null)
65 return true;
64 return true;
66
65
67 while (op != m_boundOperation && op.Level > m_boundOperation.Level)
66 while (op != m_boundOperation && op.Level > m_boundOperation.Level)
68 op = op.Parent;
67 op = op.Parent;
69 return op == m_boundOperation;
68 return op == m_boundOperation;
70 }
69 }
71
70
72 public void Unsubscribe<TEvent>(LogChannel<TEvent> channel) {
71 public void Unsubscribe<TEvent>(LogChannel<TEvent> channel) {
73 if (channel == null)
72 if (channel == null)
74 throw new ArgumentNullException("channel");
73 throw new ArgumentNullException("channel");
75
74
76 lock (m_subscriptions) {
75 lock (m_subscriptions) {
77 Action subscription;
76 Action subscription;
78 if (m_subscriptions.TryGetValue(channel, out subscription)) {
77 if (m_subscriptions.TryGetValue(channel, out subscription)) {
79 subscription();
78 subscription();
80 m_subscriptions.Remove(channel);
79 m_subscriptions.Remove(channel);
81 }
80 }
82 }
81 }
83 }
82 }
84
83
85 public void UnsubscribeAll() {
84 public void UnsubscribeAll() {
86 lock (m_subscriptions) {
85 lock (m_subscriptions) {
87 foreach (var subscription in m_subscriptions.Values)
86 foreach (var subscription in m_subscriptions.Values)
88 subscription();
87 subscription();
89 m_subscriptions.Clear();
88 m_subscriptions.Clear();
90 }
89 }
91 }
90 }
92
91
93 /// <summary>
92 /// <summary>
94 /// ВызываСтся для записи тСкста сообщСния, Π² ΠΆΡƒΡ€Π½Π°Π».
93 /// ВызываСтся для записи тСкста сообщСния, Π² ΠΆΡƒΡ€Π½Π°Π».
95 /// </summary>
94 /// </summary>
96 /// <remarks>
95 /// <remarks>
97 /// Π”Π°Π½Π½Ρ‹ΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ ΠΌΠΎΠΆΠ΅Ρ‚ Π²Ρ‹Π·Π²Π°Ρ‚ΡŒΡΡ ΠΈΠ· Ρ€Π°Π·Π½Ρ‹Ρ… ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ. Π’ΠΎΠ·ΠΌΠΎΠΆΠ½Π° ситуация, ΠΊΠΎΠ³Π΄Π°
96 /// Π”Π°Π½Π½Ρ‹ΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ ΠΌΠΎΠΆΠ΅Ρ‚ Π²Ρ‹Π·Π²Π°Ρ‚ΡŒΡΡ ΠΈΠ· Ρ€Π°Π·Π½Ρ‹Ρ… ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ. Π’ΠΎΠ·ΠΌΠΎΠΆΠ½Π° ситуация, ΠΊΠΎΠ³Π΄Π°
98 /// Π΄Π°Π½Π½Ρ‹ΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ вызываСтся ΡƒΠΆΠ΅ послС освобоТдСния ΠΎΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠΌ <see cref="Dispose()"/>.
97 /// Π΄Π°Π½Π½Ρ‹ΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ вызываСтся ΡƒΠΆΠ΅ послС освобоТдСния ΠΎΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠΌ <see cref="Dispose()"/>.
99 /// </remarks>
98 /// </remarks>
100 /// <param name="context">ΠšΠΎΠ½Ρ‚Π΅ΠΊΡΡ‚ трассировки.</param>
101 /// <param name="text">ВСкст сообщСния.</param>
99 /// <param name="text">ВСкст сообщСния.</param>
102 protected abstract void WriteEntry(TraceContext context, EventText text, string channel);
100 /// <param name = "channel"></param>
101 protected abstract void WriteEntry(LogEventArgs args, EventText text, string channel);
103
102
104 public EventText Format(TraceContext context, object data) {
103 public EventText Format(LogEventArgs args, object data) {
105 return new EventText {
104 return new EventText {
106 indent = context.CurrentOperation.Level,
105 indent = args.Operation.Level,
107 content = data.ToString()
106 content = data.ToString()
108 };
107 };
109 }
108 }
110
109
111 public EventText Format(TraceContext context, TraceEvent data) {
110 public EventText Format(LogEventArgs args, TraceEvent data) {
112 var level = context.CurrentOperation.Level;
111 var level = args.Operation.Level;
113 if (data.EventType == TraceEventType.OperationCompleted || data.EventType == TraceEventType.OperationStarted)
112 if (data.EventType == TraceEventType.OperationCompleted || data.EventType == TraceEventType.OperationStarted)
114 level--;
113 level--;
115
114
116 return new EventText {
115 return new EventText {
117 indent = level,
116 indent = level,
118 content = data.ToString()
117 content = data.ToString()
119 };
118 };
120 }
119 }
121
120
122 protected override void Dispose(bool disposing) {
121 protected override void Dispose(bool disposing) {
123 base.Dispose(disposing);
122 base.Dispose(disposing);
124 if (disposing) {
123 if (disposing) {
125 UnsubscribeAll();
124 UnsubscribeAll();
126 }
125 }
127 }
126 }
128 }
127 }
129 }
128 }
@@ -1,238 +1,79
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.Linq;
3 using System.Threading;
4 using System.Text;
4
5 using System.Threading;
5 namespace Implab.Diagnostics {
6 using System.Threading.Tasks;
6 /// <summary>
7
7 /// Trace context is bound to the specific thread, each thread has it's own ThreadContext.
8 namespace Implab.Diagnostics {
8 /// </summary>
9 /// <summary>
9 /// <remarks>
10 /// ΠšΠΎΠ½Ρ‚Π΅ΠΊΡΡ‚ трассировки, привязываСтся ΠΊ ΠΏΠΎΡ‚ΠΎΠΊΡƒ ΠΈ содСрТит Π² сСбС ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎ стСкС логичСских ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ.
10 /// ThreadContext manages relations between logical operations and threads.
11 /// </summary>
11 /// </remarks>
12 /// <remarks>
12 public class TraceContext {
13 /// ΠšΠΎΠ½Ρ‚Π΅ΠΊΡΡ‚ трассировки пСрСдаСтся ΡΠ»ΡƒΡˆΠ°Ρ‚Π΅Π»ΡΠΌ событий для опрСдСлСния мСста, Π³Π΄Π΅ Π²ΠΎΠ·Π½ΠΈΠΊΠ»ΠΎ событиС.
13
14 /// </remarks>
14 [ThreadStatic]
15 public class TraceContext {
15 static TraceContext _instance;
16 LogicalOperation m_currentOperation;
16
17 readonly LogicalOperation m_bound;
17 OperationContext m_current = OperationContext.EMPTY;
18 readonly int m_threadId;
18 readonly Stack<OperationContext> m_stack = new Stack<OperationContext>();
19
19 readonly int m_threadId;
20 [ThreadStatic]
20
21 static TraceContext _current;
21 public static TraceContext Instance {
22
22 get {
23 /// <summary>
23 if (_instance == null)
24 /// Π’Π΅ΠΊΡƒΡ‰ΠΈΠΉ контСкст трассировки для ΠΏΠΎΡ‚ΠΎΠΊΠ°, создаСтся астоматичСски ΠΏΡ€ΠΈ ΠΏΠ΅Ρ€Π²ΠΎΠΌ ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠΈ.
24 _instance = new TraceContext();
25 /// </summary>
25 return _instance;
26 public static TraceContext Current {
26 }
27 get {
27 }
28 if (_current == null) {
28
29 _current = new TraceContext();
29 public TraceContext() {
30 _current.LogEvent(TraceEventType.Created,"[{0}]", _current.ThreadId);
30 m_threadId = Thread.CurrentThread.ManagedThreadId;
31 }
31 }
32 return _current;
32
33 }
33 public int ThreadId {
34 }
34 get { return m_threadId; }
35
35 }
36 TraceContext(TraceContext context)
36
37 : this(context, false) {
37 public LogicalOperation CurrentOperation {
38 }
38 get {
39
39 return m_current.CurrentOperation;
40 TraceContext(TraceContext context, bool attach) {
40 }
41 if (context == null)
41 }
42 throw new ArgumentNullException("context");
42
43
43 public void EnterLogicalOperation(LogicalOperation operation, bool takeOwnership) {
44 m_currentOperation = context.CurrentOperation;
44 // TODO Emit event
45 m_bound = attach ? context.BoundOperation : context.CurrentOperation;
45 m_stack.Push(m_current);
46 m_threadId = Thread.CurrentThread.ManagedThreadId;
46 m_current = new OperationContext(operation, takeOwnership);
47 }
47 }
48
48
49 TraceContext() {
49 public void StartLogicalOperation(string name) {
50 m_currentOperation = new LogicalOperation();
50 m_current.BeginLogicalOperation(name);
51 m_bound = m_currentOperation;
51 }
52 m_threadId = Thread.CurrentThread.ManagedThreadId;
52
53 }
53 public void StartLogicalOperation() {
54
54 // TODO Emit Event
55 /// <summary>
55 m_current.BeginLogicalOperation(String.Empty);
56 /// ΠŸΡ€ΠΈ нСобходимости ΠΊΠΎΠΏΠΈΡ€ΡƒΠ΅Ρ‚ состояниС контСкста трассивровки Π² Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΉ ΠΏΠΎΡ‚ΠΎΠΊ.
56 }
57 /// </summary>
57
58 /// <param name="from">Π˜ΡΡ…ΠΎΠ΄Π½Ρ‹ΠΉ контСкст трассировки, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ пСрСдаСтся.</param>
58 public void EndLogicalOperation() {
59 /// <remarks>
59 // TODO Emit event
60 /// <para>
60 m_current.EndLogicalOperation();
61 /// ΠšΠΎΠΏΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ происходит Π·Π° счСт создания Π½ΠΎΠ²ΠΎΠ³ΠΎ контСкста трассировки ΠΈ Π·Π°ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ΠΌ Π΅Π³ΠΎ
61 }
62 /// состояния ΠΈΠ· ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½ΠΎΠ³ΠΎ контСкста. ΠŸΡ€ΠΈ этом копируСтся стСк ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ, ΠΎΠ΄Π½Π°ΠΊΠΎ Π² Π½ΠΎΠ²ΠΎΠΌ
62
63 /// контСкстС Ρ€Π°Π½Π΅Π΅ Π½Π°Ρ‡Π°Ρ‚Ρ‹Π΅ логичСскиС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ Π½Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½Ρ‹.
63 public LogicalOperation DetachLogicalOperation() {
64 /// </para>
64 // TODO Emit event
65 /// <para>
65 return m_current.DetachLogicalOperation();
66 /// Если ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Π° состояния ΡΠΎΡΡ‚ΠΎΡΠ»Π°ΡΡŒ, Ρ‚ΠΎ вызываСтся событиС трассировки <see cref="TraceEventType.Fork"/>.
66 }
67 /// </para>
67
68 /// </remarks>
68 public void Leave() {
69 public static void Fork(TraceContext from) {
69 // TODO Emit event
70 if (_current == from)
70 if (m_stack.Count > 0)
71 return;
71 m_current = m_stack.Pop();
72 if (from != null) {
72 else {
73 var context = new TraceContext(from);
73 TraceLog.TraceWarning("Attemtp to leave the last operation context");
74 context.LogEvent(TraceEventType.Fork, "[{0}]-->[{1}]",from.ThreadId, context.ThreadId);
74 m_current = OperationContext.EMPTY;
75 _current = context;
75 }
76 } else {
76 }
77 _current = new TraceContext();
77 }
78 }
78 }
79 }
79
80
81 /// <summary>
82 /// Π—Π°Π΄Π°Π΅Ρ‚ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌΡƒ ΠΏΠΎΡ‚ΠΎΠΊΡƒ ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹ΠΉ контСкст, Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ ΠΏΠΎΡ‚ΠΎΠΊ ΠΌΠΎΠΆΠ΅Ρ‚ Π·Π°ΠΊΠ°Π½Ρ‡ΠΈΠ²Π°Ρ‚ΡŒ Ρ€Π°Π½Π΅Π΅ Π½Π°Ρ‡Π°Ρ‚Ρ‹Π΅
83 /// логичСскиС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ Π² ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΌ контСкстС.
84 /// </summary>
85 /// <param name="source"></param>
86 public static void Attach(TraceContext source) {
87 if (_current == source)
88 return;
89 if (source != null) {
90 var context = new TraceContext(source, true);
91 context.LogEvent(TraceEventType.Attach, "[{0}]-->[{1}]", source.ThreadId, context.ThreadId);
92 _current = context;
93 } else {
94 _current = new TraceContext();
95 }
96 }
97
98 /// <summary>
99 /// ΠžΡ‚ΡΠΎΠ΅Π΄ΠΈΠ½ΡΠ΅Ρ‚ Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΉ контСкст трассировки ΠΎΡ‚ ΠΏΠΎΡ‚ΠΎΠΊΠ°, для дальнСйшСй Π΅Π³ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ Π΄Ρ€ΡƒΠ³ΠΎΠΌΡƒ ΠΏΠΎΡ‚ΠΎΠΊΡƒ
100 /// <see cref="Attach(TraceContext)"/>.
101 /// </summary>
102 /// <returns>ΠšΠΎΠ½Ρ‚Π΅ΠΊΡΡ‚ трассировки ΠΏΠΎΡ‚ΠΎΠΊΠ°</returns>
103 /// <remarks>
104 /// ПослС отсоСдинСния контСкста трассировки ΠΎΡ‚ ΠΏΠΎΡ‚ΠΎΠΊΠ°, ΠΏΡ€ΠΈ ΠΏΠ΅Ρ€Π²ΠΎΠΌ ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠΈ ΠΊ трассировкС Π² этом
105 /// ΠΏΠΎΡ‚ΠΎΠΊΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ создан Π½ΠΎΠ²Ρ‹ΠΉ контСкст.
106 /// </remarks>
107 public static TraceContext Detach() {
108 var context = Current;
109 context.LogEvent(TraceEventType.Detach, null);
110 _current = null;
111 return context;
112 }
113
114 /// <summary>
115 /// Π‘ΠΎΠ·Π΄Π°Π΅Ρ‚ ΠΏΠΎΡΡ‚ΠΎΡΠ½Π½ΡƒΡŽ копию Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π³ΠΎ контСкста, Π΄Π°Π½Π½ΡƒΡŽ копию ΠΌΠΎΠΆΠ½ΠΎ Ρ…Ρ€Π°Π½ΠΈΡ‚ΡŒ ΠΈ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ для ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ Ρ‡Π΅Ρ€Π΅Π· <see cref="Fork(TraceContext)"/>
116 /// </summary>
117 /// <returns>Копия Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π³ΠΎ контСкста трассировки.</returns>
118 public static TraceContext Snapshot() {
119 return _current == null ? new TraceContext() : new TraceContext(_current,false);
120 }
121
122 /// <summary>
123 /// ВыполняСт ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½ΠΎΠ΅ дСйствиС Π² ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΌ контСкстС трассировки, ΠΏΠΎ ΠΎΠΊΠΎΠ½Ρ‡Π°Π½ΠΈΠΈ восстанавливаСт ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΠΈΠΉ контСкст трассировки ΠΏΠΎΡ‚ΠΎΠΊΠ°.
124 /// </summary>
125 /// <param name="action"></param>
126 public void Invoke(Action action) {
127 if (action == null)
128 throw new ArgumentNullException("action");
129 var old = _current;
130 Fork(this);
131 try {
132 action();
133 } finally {
134 if(_current != null)
135 _current.EndAllOperations();
136 _current = old;
137 }
138 }
139
140 /// <summary>
141 /// ВСкущая логичСская опСрация.
142 /// </summary>
143 public LogicalOperation CurrentOperation {
144 get {
145 return m_currentOperation;
146 }
147 }
148
149 /// <summary>
150 /// ΠžΠΏΠ΅Ρ€Π°Ρ†ΠΈΡ Π½ΠΈΠΆΠ΅ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ нСльзя ΠΎΠΏΡƒΡΠΊΠ°Ρ‚ΡŒΡΡ Π² стСкС логичСских ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ, Ρ‚.Π΅. ΠΎΠ½Π° Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½Π° Π² Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌ контСкстС.
151 /// </summary>
152 public LogicalOperation BoundOperation {
153 get {
154 return m_bound;
155 }
156 }
157
158 /// <summary>
159 /// ΠŸΠΎΡ‚ΠΎΠΊ, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ создан контСкст трассировки.
160 /// </summary>
161 public int ThreadId {
162 get {
163 return m_threadId;
164 }
165 }
166
167 /// <summary>
168 /// НачинаСт Π±Π΅Π·Ρ‹ΠΌΡΠ½Π½ΡƒΡŽ Π»ΠΎΠ³ΠΈΡ‡Π΅ΡΠΊΡƒΡŽ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ.
169 /// </summary>
170 public void StartLogicalOperation() {
171 StartLogicalOperation(null);
172 }
173
174 /// <summary>
175 /// НачинаСт Π»ΠΎΠ³ΠΈΡ‡Π΅ΡΠΊΡƒΡŽ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ с ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹ΠΌ ΠΈΠΌΠ΅Π½Π΅ΠΌ. Бозданная опСрация Π±ΡƒΠ΄Π΅Ρ‚ Π΄ΠΎΠ±Π²Π°Π»Π΅Π½Π° Π² стСк логичСских ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ контСкста, Π·Π°Ρ‚Π΅ΠΌ Π±ΡƒΠ΄Π΅Ρ‚ создано ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΠ²ΡƒΡŽΡ‰Π΅Π΅ событиС.
176 /// </summary>
177 /// <param name="name">Имя Π½Π°Ρ‡ΠΈΠ½Π°Π΅ΠΌΠΎΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</param>
178 public void StartLogicalOperation(string name) {
179 m_currentOperation = new LogicalOperation(name, m_currentOperation);
180 LogEvent(TraceEventType.OperationStarted, name);
181 }
182
183 /// <summary>
184 /// Π—Π°ΠΊΠ°Π½Ρ‡ΠΈΠ²Π°Π΅Ρ‚ Π»ΠΎΠ³ΠΈΡ‡Π΅ΡΠΊΡƒΡŽ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ Π½Π°Ρ‡Π°Ρ‚ΡƒΡŽ Π² Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌ контСкстС. ΠžΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, Π½Π°Ρ‡Π°Ρ‚Ρ‹Π΅ Π² Π΄Ρ€ΡƒΠ³ΠΈΡ… контСкстах Π½Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ Π·Π°ΠΊΠΎΠ½Ρ‡Π΅Π½Ρ‹ Π² Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌ контСкстС.
185 /// </summary>
186 /// <remarks>
187 /// ΠŸΡ€ΠΈ Π²Ρ‹Π·ΠΎΠ²Π΅ Π΄Π°Π½Π½ΠΎΠ³ΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄Π° создаСтся событиС ΠΆΡƒΡ€Π½Π°Π»Π° трассировки, Π»ΠΈΠ±ΠΎ ΠΎ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, Π»ΠΈΠ±ΠΎ ΠΎΠ± ошибки, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ данная опСрация
188 /// Π½Π°Ρ‡Π°Ρ‚Π° Π² Π΄Ρ€ΡƒΠ³ΠΎΠΌ контСкстС.
189 /// </remarks>
190 public void EndLogicalOperation() {
191 if (m_bound == m_currentOperation) {
192 LogEvent(TraceEventType.Error, "Trying to end the operation which isn't belongs to current trace");
193 } else {
194 var op = m_currentOperation;
195 LogEvent(TraceEventType.OperationCompleted, "{0} {1} ms", op.Name, op.Duration);
196 m_currentOperation = m_currentOperation.Parent;
197 }
198 }
199
200 /// <summary>
201 /// Π‘ΠΎΠ·Π΄Π°Π΅Ρ‚ копию контСкста ΠΈ возвращаСтся Π½Π° ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΡƒΡŽ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ Π² Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌ контСкстС, это позволяСт Π½Π°Ρ‡Π°Ρ‚ΡŒ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΏΠΎΡ‚ΠΎΠΊΠ΅, Π° Π·Π°Π²Π΅Ρ€ΡˆΠΈΡ‚ΡŒ - Π² Π΄Ρ€ΡƒΠ³ΠΎΠΌ.
202 /// </summary>
203 /// <returns>ΠšΠΎΠ½Ρ‚Π΅ΠΊΡΡ‚ трассировки, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€ΠΈΡΠΎΠ΅Π΄ΠΈΠ½ΠΈΡ‚ΡŒ ΠΊ Π΄Ρ€ΡƒΠ³ΠΎΠΌΡƒ ΠΏΠΎΡ‚ΠΎΠΊΡƒ.</returns>
204 public TraceContext DetachLogicalOperation() {
205 if (m_bound == m_currentOperation) {
206 return new TraceContext();
207 } else {
208 var detached = new TraceContext(this, true);
209 m_currentOperation = m_currentOperation.Parent;
210 return detached;
211 }
212 }
213
214 public void BindLogicalOperationToPromise(IPromise promise) {
215 Safe.ArgumentNotNull(promise, "promise");
216
217 var ctx = DetachLogicalOperation();
218 promise.Anyway(() => {
219 var old = _current;
220 TraceContext.Attach(ctx);
221 TraceContext.Current.EndLogicalOperation();
222 _current = old;
223 });
224 }
225
226 /// <summary>
227 /// Π—Π°Π²Ρ€Π΅ΡˆΠ°Π΅Ρ‚ всС Π½Π°Ρ‡Π°Ρ‚Ρ‹Π΅ Π² этом контСкстС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ
228 /// </summary>
229 public void EndAllOperations() {
230 while (m_bound != m_currentOperation)
231 EndLogicalOperation();
232 }
233
234 void LogEvent(TraceEventType type, string format, params object[] args) {
235 LogChannel<TraceEvent>.Default.LogEvent(this, TraceEvent.Create(type, format, args));
236 }
237 }
238 }
@@ -1,55 +1,50
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.Diagnostics;
3 using System.Diagnostics;
4 using System.Linq;
4 using System.Linq;
5 using System.Text;
5 using System.Text;
6 using System.Threading.Tasks;
6 using System.Threading.Tasks;
7
7
8 namespace Implab.Diagnostics {
8 namespace Implab.Diagnostics {
9 /// <summary>
9 /// <summary>
10 /// Класс для ΠΏΡƒΠ±Π»ΠΈΠΊΠ°Ρ†ΠΈΠΈ событий выполнСния ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹, события ΠΏΡƒΠ±Π»ΠΈΠΊΡƒΡŽΡ‚ΡΡ Ρ‡Π΅Ρ€Π΅Π· <see cref="LogChannel{TraceEvent}"/>.
10 /// Класс для ΠΏΡƒΠ±Π»ΠΈΠΊΠ°Ρ†ΠΈΠΈ событий выполнСния ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹, события ΠΏΡƒΠ±Π»ΠΈΠΊΡƒΡŽΡ‚ΡΡ Ρ‡Π΅Ρ€Π΅Π· <see cref="LogChannel{TraceEvent}"/>.
11 /// Π–ΡƒΡ€Π½Π°Π» трассировки ΠΎΡ‚Ρ€Π°ΠΆΠ°Π΅Ρ‚ логичСский Ρ…ΠΎΠ΄ выполнСния ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ ΠΈ сущСствуСт всСгда, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ тСсно связан с
11 /// Π–ΡƒΡ€Π½Π°Π» трассировки ΠΎΡ‚Ρ€Π°ΠΆΠ°Π΅Ρ‚ логичСский Ρ…ΠΎΠ΄ выполнСния ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ ΠΈ сущСствуСт всСгда, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ тСсно связан с
12 /// контСкстом трассировки.
12 /// контСкстом трассировки.
13 /// </summary>
13 /// </summary>
14 public static class TraceLog {
14 public static class TraceLog {
15 [Conditional("TRACE")]
15 [Conditional("TRACE")]
16 public static void StartLogicalOperation() {
16 public static void StartLogicalOperation() {
17 TraceContext.Current.StartLogicalOperation();
17 TraceContext.Instance.StartLogicalOperation();
18 }
18 }
19
19
20 [Conditional("TRACE")]
20 [Conditional("TRACE")]
21 public static void StartLogicalOperation(string name) {
21 public static void StartLogicalOperation(string name) {
22 TraceContext.Current.StartLogicalOperation(name);
22 TraceContext.Instance.StartLogicalOperation(name);
23 }
23 }
24
24
25 [Conditional("TRACE")]
25 [Conditional("TRACE")]
26 public static void EndLogicalOperation() {
26 public static void EndLogicalOperation() {
27 TraceContext.Current.EndLogicalOperation();
27 TraceContext.Instance.EndLogicalOperation();
28 }
29
30 [Conditional("TRACE")]
31 public static void BindLogicalOperationToPromise(IPromise promise) {
32 TraceContext.Current.BindLogicalOperationToPromise(promise);
33 }
28 }
34
29
35 [Conditional("TRACE")]
30 [Conditional("TRACE")]
36 public static void TraceInformation(string format, params object[] arguments) {
31 public static void TraceInformation(string format, params object[] arguments) {
37 LogChannel<TraceEvent>.Default.LogEvent(TraceEvent.Create(TraceEventType.Information, format, arguments));
32 LogChannel<TraceEvent>.Default.LogEvent(TraceEvent.Create(TraceEventType.Information, format, arguments));
38 }
33 }
39
34
40 [Conditional("TRACE")]
35 [Conditional("TRACE")]
41 public static void TraceWarning(string format, params object[] arguments) {
36 public static void TraceWarning(string format, params object[] arguments) {
42 LogChannel<TraceEvent>.Default.LogEvent(TraceEvent.Create(TraceEventType.Warning, format, arguments));
37 LogChannel<TraceEvent>.Default.LogEvent(TraceEvent.Create(TraceEventType.Warning, format, arguments));
43 }
38 }
44
39
45 [Conditional("TRACE")]
40 [Conditional("TRACE")]
46 public static void TraceError(string format, params object[] arguments) {
41 public static void TraceError(string format, params object[] arguments) {
47 LogChannel<TraceEvent>.Default.LogEvent(TraceEvent.Create(TraceEventType.Error, format, arguments));
42 LogChannel<TraceEvent>.Default.LogEvent(TraceEvent.Create(TraceEventType.Error, format, arguments));
48 }
43 }
49
44
50 [Conditional("TRACE")]
45 [Conditional("TRACE")]
51 public static void TraceError(Exception err) {
46 public static void TraceError(Exception err) {
52 TraceError("{0}", err);
47 TraceError("{0}", err);
53 }
48 }
54 }
49 }
55 }
50 }
@@ -1,216 +1,220
1 ο»Ώ<?xml version="1.0" encoding="utf-8"?>
1 ο»Ώ<?xml version="1.0" encoding="utf-8"?>
2 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
2 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3 <PropertyGroup>
3 <PropertyGroup>
4 <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
4 <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
5 <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
5 <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
6 <ProjectGuid>{F550F1F8-8746-4AD0-9614-855F4C4B7F05}</ProjectGuid>
6 <ProjectGuid>{F550F1F8-8746-4AD0-9614-855F4C4B7F05}</ProjectGuid>
7 <OutputType>Library</OutputType>
7 <OutputType>Library</OutputType>
8 <RootNamespace>Implab</RootNamespace>
8 <RootNamespace>Implab</RootNamespace>
9 <AssemblyName>Implab</AssemblyName>
9 <AssemblyName>Implab</AssemblyName>
10 </PropertyGroup>
10 </PropertyGroup>
11 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
11 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
12 <DebugSymbols>true</DebugSymbols>
12 <DebugSymbols>true</DebugSymbols>
13 <DebugType>full</DebugType>
13 <DebugType>full</DebugType>
14 <Optimize>false</Optimize>
14 <Optimize>false</Optimize>
15 <OutputPath>bin\Debug</OutputPath>
15 <OutputPath>bin\Debug</OutputPath>
16 <DefineConstants>TRACE;DEBUG;</DefineConstants>
16 <DefineConstants>TRACE;DEBUG;</DefineConstants>
17 <ErrorReport>prompt</ErrorReport>
17 <ErrorReport>prompt</ErrorReport>
18 <WarningLevel>4</WarningLevel>
18 <WarningLevel>4</WarningLevel>
19 <ConsolePause>false</ConsolePause>
19 <ConsolePause>false</ConsolePause>
20 <RunCodeAnalysis>true</RunCodeAnalysis>
20 <RunCodeAnalysis>true</RunCodeAnalysis>
21 </PropertyGroup>
21 </PropertyGroup>
22 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
22 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
23 <DebugType>full</DebugType>
23 <DebugType>full</DebugType>
24 <Optimize>true</Optimize>
24 <Optimize>true</Optimize>
25 <OutputPath>bin\Release</OutputPath>
25 <OutputPath>bin\Release</OutputPath>
26 <ErrorReport>prompt</ErrorReport>
26 <ErrorReport>prompt</ErrorReport>
27 <WarningLevel>4</WarningLevel>
27 <WarningLevel>4</WarningLevel>
28 <ConsolePause>false</ConsolePause>
28 <ConsolePause>false</ConsolePause>
29 </PropertyGroup>
29 </PropertyGroup>
30 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug 4.5|AnyCPU' ">
30 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug 4.5|AnyCPU' ">
31 <DebugSymbols>true</DebugSymbols>
31 <DebugSymbols>true</DebugSymbols>
32 <DebugType>full</DebugType>
32 <DebugType>full</DebugType>
33 <Optimize>false</Optimize>
33 <Optimize>false</Optimize>
34 <OutputPath>bin\Debug</OutputPath>
34 <OutputPath>bin\Debug</OutputPath>
35 <DefineConstants>TRACE;DEBUG;NET_4_5</DefineConstants>
35 <DefineConstants>TRACE;DEBUG;NET_4_5</DefineConstants>
36 <ErrorReport>prompt</ErrorReport>
36 <ErrorReport>prompt</ErrorReport>
37 <WarningLevel>4</WarningLevel>
37 <WarningLevel>4</WarningLevel>
38 <RunCodeAnalysis>true</RunCodeAnalysis>
38 <RunCodeAnalysis>true</RunCodeAnalysis>
39 <ConsolePause>false</ConsolePause>
39 <ConsolePause>false</ConsolePause>
40 </PropertyGroup>
40 </PropertyGroup>
41 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release 4.5|AnyCPU' ">
41 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release 4.5|AnyCPU' ">
42 <Optimize>true</Optimize>
42 <Optimize>true</Optimize>
43 <OutputPath>bin\Release</OutputPath>
43 <OutputPath>bin\Release</OutputPath>
44 <ErrorReport>prompt</ErrorReport>
44 <ErrorReport>prompt</ErrorReport>
45 <WarningLevel>4</WarningLevel>
45 <WarningLevel>4</WarningLevel>
46 <ConsolePause>false</ConsolePause>
46 <ConsolePause>false</ConsolePause>
47 <DefineConstants>NET_4_5</DefineConstants>
47 <DefineConstants>NET_4_5</DefineConstants>
48 </PropertyGroup>
48 </PropertyGroup>
49 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugMono|AnyCPU' ">
49 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugMono|AnyCPU' ">
50 <DebugSymbols>true</DebugSymbols>
50 <DebugSymbols>true</DebugSymbols>
51 <DebugType>full</DebugType>
51 <DebugType>full</DebugType>
52 <Optimize>false</Optimize>
52 <Optimize>false</Optimize>
53 <OutputPath>bin\Debug</OutputPath>
53 <OutputPath>bin\Debug</OutputPath>
54 <DefineConstants>TRACE;DEBUG;NET_4_5;MONO</DefineConstants>
54 <DefineConstants>TRACE;DEBUG;NET_4_5;MONO</DefineConstants>
55 <ErrorReport>prompt</ErrorReport>
55 <ErrorReport>prompt</ErrorReport>
56 <WarningLevel>4</WarningLevel>
56 <WarningLevel>4</WarningLevel>
57 <RunCodeAnalysis>true</RunCodeAnalysis>
57 <RunCodeAnalysis>true</RunCodeAnalysis>
58 <ConsolePause>false</ConsolePause>
58 <ConsolePause>false</ConsolePause>
59 </PropertyGroup>
59 </PropertyGroup>
60 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseMono|AnyCPU' ">
60 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseMono|AnyCPU' ">
61 <Optimize>true</Optimize>
61 <Optimize>true</Optimize>
62 <OutputPath>bin\Release</OutputPath>
62 <OutputPath>bin\Release</OutputPath>
63 <DefineConstants>NET_4_5;MONO;</DefineConstants>
63 <DefineConstants>NET_4_5;MONO;</DefineConstants>
64 <ErrorReport>prompt</ErrorReport>
64 <ErrorReport>prompt</ErrorReport>
65 <WarningLevel>4</WarningLevel>
65 <WarningLevel>4</WarningLevel>
66 <ConsolePause>false</ConsolePause>
66 <ConsolePause>false</ConsolePause>
67 </PropertyGroup>
67 </PropertyGroup>
68 <ItemGroup>
68 <ItemGroup>
69 <Reference Include="System" />
69 <Reference Include="System" />
70 <Reference Include="System.Xml" />
70 <Reference Include="System.Xml" />
71 </ItemGroup>
71 </ItemGroup>
72 <ItemGroup>
72 <ItemGroup>
73 <Compile Include="Component.cs" />
73 <Compile Include="Component.cs" />
74 <Compile Include="CustomEqualityComparer.cs" />
74 <Compile Include="CustomEqualityComparer.cs" />
75 <Compile Include="Diagnostics\ConsoleTraceListener.cs" />
75 <Compile Include="Diagnostics\ConsoleTraceListener.cs" />
76 <Compile Include="Diagnostics\EventText.cs" />
76 <Compile Include="Diagnostics\EventText.cs" />
77 <Compile Include="Diagnostics\IEventTextFormatter.cs" />
77 <Compile Include="Diagnostics\IEventTextFormatter.cs" />
78 <Compile Include="Diagnostics\LogChannel.cs" />
78 <Compile Include="Diagnostics\LogChannel.cs" />
79 <Compile Include="Diagnostics\LogicalOperation.cs" />
79 <Compile Include="Diagnostics\LogicalOperation.cs" />
80 <Compile Include="Diagnostics\TextFileListener.cs" />
80 <Compile Include="Diagnostics\TextFileListener.cs" />
81 <Compile Include="Diagnostics\TextListenerBase.cs" />
81 <Compile Include="Diagnostics\TextListenerBase.cs" />
82 <Compile Include="Diagnostics\TraceLog.cs" />
82 <Compile Include="Diagnostics\TraceLog.cs" />
83 <Compile Include="Diagnostics\TraceContext.cs" />
84 <Compile Include="Diagnostics\TraceEvent.cs" />
83 <Compile Include="Diagnostics\TraceEvent.cs" />
85 <Compile Include="Diagnostics\TraceEventType.cs" />
84 <Compile Include="Diagnostics\TraceEventType.cs" />
86 <Compile Include="Disposable.cs" />
85 <Compile Include="Disposable.cs" />
87 <Compile Include="ICancellable.cs" />
86 <Compile Include="ICancellable.cs" />
88 <Compile Include="IProgressHandler.cs" />
87 <Compile Include="IProgressHandler.cs" />
89 <Compile Include="IProgressNotifier.cs" />
88 <Compile Include="IProgressNotifier.cs" />
90 <Compile Include="IPromiseT.cs" />
89 <Compile Include="IPromiseT.cs" />
91 <Compile Include="IPromise.cs" />
90 <Compile Include="IPromise.cs" />
92 <Compile Include="IServiceLocator.cs" />
91 <Compile Include="IServiceLocator.cs" />
93 <Compile Include="ITaskController.cs" />
92 <Compile Include="ITaskController.cs" />
94 <Compile Include="JSON\JSONElementContext.cs" />
93 <Compile Include="JSON\JSONElementContext.cs" />
95 <Compile Include="JSON\JSONElementType.cs" />
94 <Compile Include="JSON\JSONElementType.cs" />
96 <Compile Include="JSON\JSONGrammar.cs" />
95 <Compile Include="JSON\JSONGrammar.cs" />
97 <Compile Include="JSON\JSONParser.cs" />
96 <Compile Include="JSON\JSONParser.cs" />
98 <Compile Include="JSON\JSONScanner.cs" />
97 <Compile Include="JSON\JSONScanner.cs" />
99 <Compile Include="JSON\JsonTokenType.cs" />
98 <Compile Include="JSON\JsonTokenType.cs" />
100 <Compile Include="JSON\JSONWriter.cs" />
99 <Compile Include="JSON\JSONWriter.cs" />
101 <Compile Include="JSON\JSONXmlReader.cs" />
100 <Compile Include="JSON\JSONXmlReader.cs" />
102 <Compile Include="JSON\JSONXmlReaderOptions.cs" />
101 <Compile Include="JSON\JSONXmlReaderOptions.cs" />
103 <Compile Include="JSON\StringTranslator.cs" />
102 <Compile Include="JSON\StringTranslator.cs" />
104 <Compile Include="Parallels\DispatchPool.cs" />
103 <Compile Include="Parallels\DispatchPool.cs" />
105 <Compile Include="Parallels\ArrayTraits.cs" />
104 <Compile Include="Parallels\ArrayTraits.cs" />
106 <Compile Include="Parallels\MTQueue.cs" />
105 <Compile Include="Parallels\MTQueue.cs" />
107 <Compile Include="Parallels\WorkerPool.cs" />
106 <Compile Include="Parallels\WorkerPool.cs" />
108 <Compile Include="Parsing\Alphabet.cs" />
107 <Compile Include="Parsing\Alphabet.cs" />
109 <Compile Include="Parsing\AlphabetBase.cs" />
108 <Compile Include="Parsing\AlphabetBase.cs" />
110 <Compile Include="Parsing\AltToken.cs" />
109 <Compile Include="Parsing\AltToken.cs" />
111 <Compile Include="Parsing\BinaryToken.cs" />
110 <Compile Include="Parsing\BinaryToken.cs" />
112 <Compile Include="Parsing\CatToken.cs" />
111 <Compile Include="Parsing\CatToken.cs" />
113 <Compile Include="Parsing\CDFADefinition.cs" />
112 <Compile Include="Parsing\CDFADefinition.cs" />
114 <Compile Include="Parsing\DFABuilder.cs" />
113 <Compile Include="Parsing\DFABuilder.cs" />
115 <Compile Include="Parsing\DFADefinitionBase.cs" />
114 <Compile Include="Parsing\DFADefinitionBase.cs" />
116 <Compile Include="Parsing\DFAStateDescriptor.cs" />
115 <Compile Include="Parsing\DFAStateDescriptor.cs" />
117 <Compile Include="Parsing\DFAutomaton.cs" />
116 <Compile Include="Parsing\DFAutomaton.cs" />
118 <Compile Include="Parsing\EDFADefinition.cs" />
117 <Compile Include="Parsing\EDFADefinition.cs" />
119 <Compile Include="Parsing\EmptyToken.cs" />
118 <Compile Include="Parsing\EmptyToken.cs" />
120 <Compile Include="Parsing\EndToken.cs" />
119 <Compile Include="Parsing\EndToken.cs" />
121 <Compile Include="Parsing\EnumAlphabet.cs" />
120 <Compile Include="Parsing\EnumAlphabet.cs" />
122 <Compile Include="Parsing\Grammar.cs" />
121 <Compile Include="Parsing\Grammar.cs" />
123 <Compile Include="Parsing\IAlphabet.cs" />
122 <Compile Include="Parsing\IAlphabet.cs" />
124 <Compile Include="Parsing\IDFADefinition.cs" />
123 <Compile Include="Parsing\IDFADefinition.cs" />
125 <Compile Include="Parsing\IVisitor.cs" />
124 <Compile Include="Parsing\IVisitor.cs" />
126 <Compile Include="Parsing\ParserException.cs" />
125 <Compile Include="Parsing\ParserException.cs" />
127 <Compile Include="Parsing\Scanner.cs" />
126 <Compile Include="Parsing\Scanner.cs" />
128 <Compile Include="Parsing\StarToken.cs" />
127 <Compile Include="Parsing\StarToken.cs" />
129 <Compile Include="Parsing\SymbolToken.cs" />
128 <Compile Include="Parsing\SymbolToken.cs" />
130 <Compile Include="Parsing\Token.cs" />
129 <Compile Include="Parsing\Token.cs" />
131 <Compile Include="SafePool.cs" />
130 <Compile Include="SafePool.cs" />
132 <Compile Include="ServiceLocator.cs" />
131 <Compile Include="ServiceLocator.cs" />
133 <Compile Include="TaskController.cs" />
132 <Compile Include="TaskController.cs" />
134 <Compile Include="ProgressInitEventArgs.cs" />
133 <Compile Include="ProgressInitEventArgs.cs" />
135 <Compile Include="Properties\AssemblyInfo.cs" />
134 <Compile Include="Properties\AssemblyInfo.cs" />
136 <Compile Include="Promise.cs" />
135 <Compile Include="Promise.cs" />
137 <Compile Include="Parallels\AsyncPool.cs" />
136 <Compile Include="Parallels\AsyncPool.cs" />
138 <Compile Include="Safe.cs" />
137 <Compile Include="Safe.cs" />
139 <Compile Include="ValueEventArgs.cs" />
138 <Compile Include="ValueEventArgs.cs" />
140 <Compile Include="PromiseExtensions.cs" />
139 <Compile Include="PromiseExtensions.cs" />
141 <Compile Include="TransientPromiseException.cs" />
140 <Compile Include="TransientPromiseException.cs" />
142 <Compile Include="SyncContextPromise.cs" />
141 <Compile Include="SyncContextPromise.cs" />
143 <Compile Include="ObjectPool.cs" />
142 <Compile Include="ObjectPool.cs" />
143 <Compile Include="Diagnostics\OperationContext.cs" />
144 <Compile Include="Diagnostics\TraceContext.cs" />
145 <Compile Include="Diagnostics\LogEventArgs.cs" />
146 <Compile Include="Diagnostics\LogEventArgsT.cs" />
147 <Compile Include="Diagnostics\Extensions.cs" />
144 </ItemGroup>
148 </ItemGroup>
145 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
149 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
146 <ItemGroup />
150 <ItemGroup />
147 <ProjectExtensions>
151 <ProjectExtensions>
148 <MonoDevelop>
152 <MonoDevelop>
149 <Properties>
153 <Properties>
150 <Policies>
154 <Policies>
151 <CSharpFormattingPolicy IndentSwitchBody="True" NamespaceBraceStyle="EndOfLine" ClassBraceStyle="EndOfLine" InterfaceBraceStyle="EndOfLine" StructBraceStyle="EndOfLine" EnumBraceStyle="EndOfLine" MethodBraceStyle="EndOfLine" ConstructorBraceStyle="EndOfLine" DestructorBraceStyle="EndOfLine" BeforeMethodDeclarationParentheses="False" BeforeMethodCallParentheses="False" BeforeConstructorDeclarationParentheses="False" NewLineBeforeConstructorInitializerColon="NewLine" NewLineAfterConstructorInitializerColon="SameLine" BeforeIndexerDeclarationBracket="False" BeforeDelegateDeclarationParentheses="False" NewParentheses="False" SpacesBeforeBrackets="False" inheritsSet="Mono" inheritsScope="text/x-csharp" scope="text/x-csharp" />
155 <CSharpFormattingPolicy IndentSwitchBody="True" NamespaceBraceStyle="EndOfLine" ClassBraceStyle="EndOfLine" InterfaceBraceStyle="EndOfLine" StructBraceStyle="EndOfLine" EnumBraceStyle="EndOfLine" MethodBraceStyle="EndOfLine" ConstructorBraceStyle="EndOfLine" DestructorBraceStyle="EndOfLine" BeforeMethodDeclarationParentheses="False" BeforeMethodCallParentheses="False" BeforeConstructorDeclarationParentheses="False" NewLineBeforeConstructorInitializerColon="NewLine" NewLineAfterConstructorInitializerColon="SameLine" BeforeIndexerDeclarationBracket="False" BeforeDelegateDeclarationParentheses="False" NewParentheses="False" SpacesBeforeBrackets="False" inheritsSet="Mono" inheritsScope="text/x-csharp" scope="text/x-csharp" />
152 <TextStylePolicy FileWidth="120" EolMarker="Unix" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/x-csharp" />
156 <TextStylePolicy FileWidth="120" EolMarker="Unix" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/x-csharp" />
153 <DotNetNamingPolicy DirectoryNamespaceAssociation="PrefixedHierarchical" ResourceNamePolicy="MSBuild" />
157 <DotNetNamingPolicy DirectoryNamespaceAssociation="PrefixedHierarchical" ResourceNamePolicy="MSBuild" />
154 <TextStylePolicy FileWidth="120" TabsToSpaces="False" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="application/xml" />
158 <TextStylePolicy FileWidth="120" TabsToSpaces="False" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="application/xml" />
155 <XmlFormattingPolicy inheritsSet="Mono" inheritsScope="application/xml" scope="application/xml" />
159 <XmlFormattingPolicy inheritsSet="Mono" inheritsScope="application/xml" scope="application/xml" />
156 <TextStylePolicy FileWidth="120" TabsToSpaces="False" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/plain" />
160 <TextStylePolicy FileWidth="120" TabsToSpaces="False" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/plain" />
157 <NameConventionPolicy>
161 <NameConventionPolicy>
158 <Rules>
162 <Rules>
159 <NamingRule Name="Namespaces" AffectedEntity="Namespace" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
163 <NamingRule Name="Namespaces" AffectedEntity="Namespace" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
160 <NamingRule Name="Types" AffectedEntity="Class, Struct, Enum, Delegate" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
164 <NamingRule Name="Types" AffectedEntity="Class, Struct, Enum, Delegate" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
161 <NamingRule Name="Interfaces" AffectedEntity="Interface" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
165 <NamingRule Name="Interfaces" AffectedEntity="Interface" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
162 <RequiredPrefixes>
166 <RequiredPrefixes>
163 <String>I</String>
167 <String>I</String>
164 </RequiredPrefixes>
168 </RequiredPrefixes>
165 </NamingRule>
169 </NamingRule>
166 <NamingRule Name="Attributes" AffectedEntity="CustomAttributes" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
170 <NamingRule Name="Attributes" AffectedEntity="CustomAttributes" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
167 <RequiredSuffixes>
171 <RequiredSuffixes>
168 <String>Attribute</String>
172 <String>Attribute</String>
169 </RequiredSuffixes>
173 </RequiredSuffixes>
170 </NamingRule>
174 </NamingRule>
171 <NamingRule Name="Event Arguments" AffectedEntity="CustomEventArgs" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
175 <NamingRule Name="Event Arguments" AffectedEntity="CustomEventArgs" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
172 <RequiredSuffixes>
176 <RequiredSuffixes>
173 <String>EventArgs</String>
177 <String>EventArgs</String>
174 </RequiredSuffixes>
178 </RequiredSuffixes>
175 </NamingRule>
179 </NamingRule>
176 <NamingRule Name="Exceptions" AffectedEntity="CustomExceptions" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
180 <NamingRule Name="Exceptions" AffectedEntity="CustomExceptions" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
177 <RequiredSuffixes>
181 <RequiredSuffixes>
178 <String>Exception</String>
182 <String>Exception</String>
179 </RequiredSuffixes>
183 </RequiredSuffixes>
180 </NamingRule>
184 </NamingRule>
181 <NamingRule Name="Methods" AffectedEntity="Methods" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
185 <NamingRule Name="Methods" AffectedEntity="Methods" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
182 <NamingRule Name="Static Readonly Fields" AffectedEntity="ReadonlyField" VisibilityMask="Internal, Protected, Public" NamingStyle="CamelCase" IncludeInstanceMembers="False" IncludeStaticEntities="True" />
186 <NamingRule Name="Static Readonly Fields" AffectedEntity="ReadonlyField" VisibilityMask="Internal, Protected, Public" NamingStyle="CamelCase" IncludeInstanceMembers="False" IncludeStaticEntities="True" />
183 <NamingRule Name="Fields (Non Private)" AffectedEntity="Field" VisibilityMask="Internal, Public" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
187 <NamingRule Name="Fields (Non Private)" AffectedEntity="Field" VisibilityMask="Internal, Public" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
184 <NamingRule Name="ReadOnly Fields (Non Private)" AffectedEntity="ReadonlyField" VisibilityMask="Internal, Public" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False" />
188 <NamingRule Name="ReadOnly Fields (Non Private)" AffectedEntity="ReadonlyField" VisibilityMask="Internal, Public" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False" />
185 <NamingRule Name="Fields (Private)" AffectedEntity="Field, ReadonlyField" VisibilityMask="Private, Protected" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False">
189 <NamingRule Name="Fields (Private)" AffectedEntity="Field, ReadonlyField" VisibilityMask="Private, Protected" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False">
186 <RequiredPrefixes>
190 <RequiredPrefixes>
187 <String>m_</String>
191 <String>m_</String>
188 </RequiredPrefixes>
192 </RequiredPrefixes>
189 </NamingRule>
193 </NamingRule>
190 <NamingRule Name="Static Fields (Private)" AffectedEntity="Field" VisibilityMask="Private" NamingStyle="CamelCase" IncludeInstanceMembers="False" IncludeStaticEntities="True">
194 <NamingRule Name="Static Fields (Private)" AffectedEntity="Field" VisibilityMask="Private" NamingStyle="CamelCase" IncludeInstanceMembers="False" IncludeStaticEntities="True">
191 <RequiredPrefixes>
195 <RequiredPrefixes>
192 <String>_</String>
196 <String>_</String>
193 </RequiredPrefixes>
197 </RequiredPrefixes>
194 </NamingRule>
198 </NamingRule>
195 <NamingRule Name="ReadOnly Fields (Private)" AffectedEntity="ReadonlyField" VisibilityMask="Private, Protected" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False">
199 <NamingRule Name="ReadOnly Fields (Private)" AffectedEntity="ReadonlyField" VisibilityMask="Private, Protected" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False">
196 <RequiredPrefixes>
200 <RequiredPrefixes>
197 <String>m_</String>
201 <String>m_</String>
198 </RequiredPrefixes>
202 </RequiredPrefixes>
199 </NamingRule>
203 </NamingRule>
200 <NamingRule Name="Constant Fields" AffectedEntity="ConstantField" VisibilityMask="VisibilityMask" NamingStyle="AllUpper" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
204 <NamingRule Name="Constant Fields" AffectedEntity="ConstantField" VisibilityMask="VisibilityMask" NamingStyle="AllUpper" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
201 <NamingRule Name="Properties" AffectedEntity="Property" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
205 <NamingRule Name="Properties" AffectedEntity="Property" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
202 <NamingRule Name="Events" AffectedEntity="Event" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
206 <NamingRule Name="Events" AffectedEntity="Event" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
203 <NamingRule Name="Enum Members" AffectedEntity="EnumMember" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
207 <NamingRule Name="Enum Members" AffectedEntity="EnumMember" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
204 <NamingRule Name="Parameters" AffectedEntity="Parameter, LocalVariable" VisibilityMask="VisibilityMask" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
208 <NamingRule Name="Parameters" AffectedEntity="Parameter, LocalVariable" VisibilityMask="VisibilityMask" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
205 <NamingRule Name="Type Parameters" AffectedEntity="TypeParameter" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
209 <NamingRule Name="Type Parameters" AffectedEntity="TypeParameter" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
206 <RequiredPrefixes>
210 <RequiredPrefixes>
207 <String>T</String>
211 <String>T</String>
208 </RequiredPrefixes>
212 </RequiredPrefixes>
209 </NamingRule>
213 </NamingRule>
210 </Rules>
214 </Rules>
211 </NameConventionPolicy>
215 </NameConventionPolicy>
212 </Policies>
216 </Policies>
213 </Properties>
217 </Properties>
214 </MonoDevelop>
218 </MonoDevelop>
215 </ProjectExtensions>
219 </ProjectExtensions>
216 </Project> No newline at end of file
220 </Project>
@@ -1,202 +1,210
1 using Implab.Diagnostics;
1 using Implab.Diagnostics;
2 using System;
2 using System;
3 using System.Collections.Generic;
3 using System.Collections.Generic;
4 using System.Diagnostics;
4 using System.Diagnostics;
5 using System.Linq;
5 using System.Linq;
6 using System.Text;
6 using System.Text;
7 using System.Threading;
7 using System.Threading;
8
8
9 namespace Implab.Parallels {
9 namespace Implab.Parallels {
10 public static class ArrayTraits {
10 public static class ArrayTraits {
11 class ArrayIterator<TSrc> : DispatchPool<int> {
11 class ArrayIterator<TSrc> : DispatchPool<int> {
12 readonly Action<TSrc> m_action;
12 readonly Action<TSrc> m_action;
13 readonly TSrc[] m_source;
13 readonly TSrc[] m_source;
14 readonly Promise<int> m_promise = new Promise<int>();
14 readonly Promise<int> m_promise = new Promise<int>();
15 readonly TraceContext m_traceContext;
15 readonly LogicalOperation m_logicalOperation;
16
16
17 int m_pending;
17 int m_pending;
18 int m_next;
18 int m_next;
19
19
20 public ArrayIterator(TSrc[] source, Action<TSrc> action, int threads)
20 public ArrayIterator(TSrc[] source, Action<TSrc> action, int threads)
21 : base(threads) {
21 : base(threads) {
22
22
23 Debug.Assert(source != null);
23 Debug.Assert(source != null);
24 Debug.Assert(action != null);
24 Debug.Assert(action != null);
25
25
26 m_traceContext = TraceContext.Snapshot();
26 m_logicalOperation = TraceContext.Instance.CurrentOperation;
27 m_next = 0;
27 m_next = 0;
28 m_source = source;
28 m_source = source;
29 m_pending = source.Length;
29 m_pending = source.Length;
30 m_action = action;
30 m_action = action;
31
31
32 m_promise.Anyway(Dispose);
32 m_promise.Anyway(Dispose);
33
33
34 InitPool();
34 InitPool();
35 }
35 }
36
36
37 public Promise<int> Promise {
37 public Promise<int> Promise {
38 get {
38 get {
39 return m_promise;
39 return m_promise;
40 }
40 }
41 }
41 }
42
42
43 protected override void Worker() {
43 protected override void Worker() {
44 TraceContext.Fork(m_traceContext);
44 TraceContext.Instance.EnterLogicalOperation(m_logicalOperation, false);
45 base.Worker();
45 try {
46 base.Worker();
47 } finally {
48 TraceContext.Instance.Leave();
49 }
46 }
50 }
47
51
48 protected override bool TryDequeue(out int unit) {
52 protected override bool TryDequeue(out int unit) {
49 unit = Interlocked.Increment(ref m_next) - 1;
53 unit = Interlocked.Increment(ref m_next) - 1;
50 return unit < m_source.Length;
54 return unit < m_source.Length;
51 }
55 }
52
56
53 protected override void InvokeUnit(int unit) {
57 protected override void InvokeUnit(int unit) {
54 try {
58 try {
55 m_action(m_source[unit]);
59 m_action(m_source[unit]);
56 var pending = Interlocked.Decrement(ref m_pending);
60 var pending = Interlocked.Decrement(ref m_pending);
57 if (pending == 0)
61 if (pending == 0)
58 m_promise.Resolve(m_source.Length);
62 m_promise.Resolve(m_source.Length);
59 } catch (Exception e) {
63 } catch (Exception e) {
60 m_promise.Reject(e);
64 m_promise.Reject(e);
61 }
65 }
62 }
66 }
63 }
67 }
64
68
65 class ArrayMapper<TSrc, TDst>: DispatchPool<int> {
69 class ArrayMapper<TSrc, TDst>: DispatchPool<int> {
66 readonly Func<TSrc, TDst> m_transform;
70 readonly Func<TSrc, TDst> m_transform;
67 readonly TSrc[] m_source;
71 readonly TSrc[] m_source;
68 readonly TDst[] m_dest;
72 readonly TDst[] m_dest;
69 readonly Promise<TDst[]> m_promise = new Promise<TDst[]>();
73 readonly Promise<TDst[]> m_promise = new Promise<TDst[]>();
70 readonly TraceContext m_traceContext;
74 readonly LogicalOperation m_logicalOperation;
71
75
72 int m_pending;
76 int m_pending;
73 int m_next;
77 int m_next;
74
78
75 public ArrayMapper(TSrc[] source, Func<TSrc, TDst> transform, int threads)
79 public ArrayMapper(TSrc[] source, Func<TSrc, TDst> transform, int threads)
76 : base(threads) {
80 : base(threads) {
77
81
78 Debug.Assert (source != null);
82 Debug.Assert (source != null);
79 Debug.Assert( transform != null);
83 Debug.Assert( transform != null);
80
84
81 m_next = 0;
85 m_next = 0;
82 m_source = source;
86 m_source = source;
83 m_dest = new TDst[source.Length];
87 m_dest = new TDst[source.Length];
84 m_pending = source.Length;
88 m_pending = source.Length;
85 m_transform = transform;
89 m_transform = transform;
86 m_traceContext = TraceContext.Snapshot();
90 m_logicalOperation = TraceContext.Instance.CurrentOperation;
87
91
88 m_promise.Anyway(Dispose);
92 m_promise.Anyway(Dispose);
89
93
90 InitPool();
94 InitPool();
91 }
95 }
92
96
93 public Promise<TDst[]> Promise {
97 public Promise<TDst[]> Promise {
94 get {
98 get {
95 return m_promise;
99 return m_promise;
96 }
100 }
97 }
101 }
98
102
99 protected override void Worker() {
103 protected override void Worker() {
100 TraceContext.Fork(m_traceContext);
104 TraceContext.Instance.EnterLogicalOperation(m_logicalOperation,false);
101 base.Worker();
105 try {
106 base.Worker();
107 } finally {
108 TraceContext.Instance.Leave();
109 }
102 }
110 }
103
111
104 protected override bool TryDequeue(out int unit) {
112 protected override bool TryDequeue(out int unit) {
105 unit = Interlocked.Increment(ref m_next) - 1;
113 unit = Interlocked.Increment(ref m_next) - 1;
106 return unit >= m_source.Length ? false : true;
114 return unit < m_source.Length;
107 }
115 }
108
116
109 protected override void InvokeUnit(int unit) {
117 protected override void InvokeUnit(int unit) {
110 try {
118 try {
111 m_dest[unit] = m_transform(m_source[unit]);
119 m_dest[unit] = m_transform(m_source[unit]);
112 var pending = Interlocked.Decrement(ref m_pending);
120 var pending = Interlocked.Decrement(ref m_pending);
113 if (pending == 0)
121 if (pending == 0)
114 m_promise.Resolve(m_dest);
122 m_promise.Resolve(m_dest);
115 } catch (Exception e) {
123 } catch (Exception e) {
116 m_promise.Reject(e);
124 m_promise.Reject(e);
117 }
125 }
118 }
126 }
119 }
127 }
120
128
121 public static IPromise<TDst[]> ParallelMap<TSrc, TDst> (this TSrc[] source, Func<TSrc,TDst> transform, int threads) {
129 public static IPromise<TDst[]> ParallelMap<TSrc, TDst> (this TSrc[] source, Func<TSrc,TDst> transform, int threads) {
122 if (source == null)
130 if (source == null)
123 throw new ArgumentNullException("source");
131 throw new ArgumentNullException("source");
124 if (transform == null)
132 if (transform == null)
125 throw new ArgumentNullException("transform");
133 throw new ArgumentNullException("transform");
126
134
127 var mapper = new ArrayMapper<TSrc, TDst>(source, transform, threads);
135 var mapper = new ArrayMapper<TSrc, TDst>(source, transform, threads);
128 return mapper.Promise;
136 return mapper.Promise;
129 }
137 }
130
138
131 public static IPromise<int> ParallelForEach<TSrc>(this TSrc[] source, Action<TSrc> action, int threads) {
139 public static IPromise<int> ParallelForEach<TSrc>(this TSrc[] source, Action<TSrc> action, int threads) {
132 if (source == null)
140 if (source == null)
133 throw new ArgumentNullException("source");
141 throw new ArgumentNullException("source");
134 if (action == null)
142 if (action == null)
135 throw new ArgumentNullException("action");
143 throw new ArgumentNullException("action");
136
144
137 var iter = new ArrayIterator<TSrc>(source, action, threads);
145 var iter = new ArrayIterator<TSrc>(source, action, threads);
138 return iter.Promise;
146 return iter.Promise;
139 }
147 }
140
148
141 public static IPromise<TDst[]> ChainedMap<TSrc, TDst>(this TSrc[] source, ResultMapper<TSrc, IPromise<TDst>> transform, int threads) {
149 public static IPromise<TDst[]> ChainedMap<TSrc, TDst>(this TSrc[] source, ResultMapper<TSrc, IPromise<TDst>> transform, int threads) {
142 if (source == null)
150 if (source == null)
143 throw new ArgumentNullException("source");
151 throw new ArgumentNullException("source");
144 if (transform == null)
152 if (transform == null)
145 throw new ArgumentNullException("transform");
153 throw new ArgumentNullException("transform");
146 if (threads <= 0)
154 if (threads <= 0)
147 throw new ArgumentOutOfRangeException("Threads number must be greater then zero");
155 throw new ArgumentOutOfRangeException("Threads number must be greater then zero");
148
156
149 if (source.Length == 0)
157 if (source.Length == 0)
150 return Promise<TDst[]>.ResultToPromise(new TDst[0]);
158 return Promise<TDst[]>.ResultToPromise(new TDst[0]);
151
159
152 var promise = new Promise<TDst[]>();
160 var promise = new Promise<TDst[]>();
153 var res = new TDst[source.Length];
161 var res = new TDst[source.Length];
154 var pending = source.Length;
162 var pending = source.Length;
155
163
156 object locker = new object();
164 object locker = new object();
157 int slots = threads;
165 int slots = threads;
158
166
159 // Analysis disable AccessToDisposedClosure
167 // Analysis disable AccessToDisposedClosure
160 AsyncPool.InvokeNewThread(() => {
168 AsyncPool.InvokeNewThread(() => {
161 for (int i = 0; i < source.Length; i++) {
169 for (int i = 0; i < source.Length; i++) {
162 if(promise.IsResolved)
170 if(promise.IsResolved)
163 break; // stop processing in case of error or cancellation
171 break; // stop processing in case of error or cancellation
164 var idx = i;
172 var idx = i;
165
173
166 if (Interlocked.Decrement(ref slots) < 0) {
174 if (Interlocked.Decrement(ref slots) < 0) {
167 lock(locker) {
175 lock(locker) {
168 while(slots < 0)
176 while(slots < 0)
169 Monitor.Wait(locker);
177 Monitor.Wait(locker);
170 }
178 }
171 }
179 }
172
180
173 try {
181 try {
174 transform(source[i])
182 transform(source[i])
175 .Anyway(() => {
183 .Anyway(() => {
176 Interlocked.Increment(ref slots);
184 Interlocked.Increment(ref slots);
177 lock (locker) {
185 lock (locker) {
178 Monitor.Pulse(locker);
186 Monitor.Pulse(locker);
179 }
187 }
180 })
188 })
181 .Last(
189 .Last(
182 x => {
190 x => {
183 res[idx] = x;
191 res[idx] = x;
184 var left = Interlocked.Decrement(ref pending);
192 var left = Interlocked.Decrement(ref pending);
185 if (left == 0)
193 if (left == 0)
186 promise.Resolve(res);
194 promise.Resolve(res);
187 },
195 },
188 promise.Reject
196 promise.Reject
189 );
197 );
190
198
191 } catch (Exception e) {
199 } catch (Exception e) {
192 promise.Reject(e);
200 promise.Reject(e);
193 }
201 }
194 }
202 }
195 return 0;
203 return 0;
196 });
204 });
197
205
198 return promise;
206 return promise;
199 }
207 }
200
208
201 }
209 }
202 }
210 }
@@ -1,71 +1,77
1 using Implab.Diagnostics;
1 using Implab.Diagnostics;
2 using System;
2 using System;
3 using System.Threading;
3 using System.Threading;
4
4
5 namespace Implab.Parallels {
5 namespace Implab.Parallels {
6 /// <summary>
6 /// <summary>
7 /// Класс для распаралСливания Π·Π°Π΄Π°Ρ‡.
7 /// Класс для распаралСливания Π·Π°Π΄Π°Ρ‡.
8 /// </summary>
8 /// </summary>
9 /// <remarks>
9 /// <remarks>
10 /// Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ Π΄Π°Π½Π½Ρ‹ΠΉ класс ΠΈ лямда выраТСния ΠΌΠΎΠΆΠ½ΠΎ Ρ€Π°ΡΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΠΈΡ‚ΡŒ
10 /// Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ Π΄Π°Π½Π½Ρ‹ΠΉ класс ΠΈ лямда выраТСния ΠΌΠΎΠΆΠ½ΠΎ Ρ€Π°ΡΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΠΈΡ‚ΡŒ
11 /// вычислСния, для этого ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ концСпция ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ.
11 /// вычислСния, для этого ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ концСпция ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ.
12 /// </remarks>
12 /// </remarks>
13 public static class AsyncPool {
13 public static class AsyncPool {
14
14
15 public static IPromise<T> Invoke<T>(Func<T> func) {
15 public static IPromise<T> Invoke<T>(Func<T> func) {
16 var p = new Promise<T>();
16 var p = new Promise<T>();
17 var caller = TraceContext.Snapshot();
17 var caller = TraceContext.Instance.CurrentOperation;
18
18
19 ThreadPool.QueueUserWorkItem(param => {
19 ThreadPool.QueueUserWorkItem(param => {
20 TraceContext.Fork(caller);
20 TraceContext.Instance.EnterLogicalOperation(caller,false);
21 try {
21 try {
22 p.Resolve(func());
22 p.Resolve(func());
23 } catch(Exception e) {
23 } catch(Exception e) {
24 p.Reject(e);
24 p.Reject(e);
25 }
25 } finally {
26 TraceContext.Instance.Leave();
27 }
26 });
28 });
27
29
28 return p;
30 return p;
29 }
31 }
30
32
31 public static IPromise<T> InvokeNewThread<T>(Func<T> func) {
33 public static IPromise<T> InvokeNewThread<T>(Func<T> func) {
32 var p = new Promise<T>();
34 var p = new Promise<T>();
33
35
34 var caller = TraceContext.Snapshot();
36 var caller = TraceContext.Instance.CurrentOperation;
35
37
36 var worker = new Thread(() => {
38 var worker = new Thread(() => {
37 TraceContext.Fork(caller);
39 TraceContext.Instance.EnterLogicalOperation(caller,false);
38 try {
40 try {
39 p.Resolve(func());
41 p.Resolve(func());
40 } catch (Exception e) {
42 } catch (Exception e) {
41 p.Reject(e);
43 p.Reject(e);
44 } finally {
45 TraceContext.Instance.Leave();
42 }
46 }
43 });
47 });
44 worker.IsBackground = true;
48 worker.IsBackground = true;
45 worker.Start();
49 worker.Start();
46
50
47 return p;
51 return p;
48 }
52 }
49
53
50
54
51 public static IPromise InvokeNewThread(Action func) {
55 public static IPromise InvokeNewThread(Action func) {
52 var p = new Promise<object>();
56 var p = new Promise<object>();
53
57
54 var caller = TraceContext.Snapshot();
58 var caller = TraceContext.Instance.CurrentOperation;
55
59
56 var worker = new Thread(() => {
60 var worker = new Thread(() => {
57 TraceContext.Fork(caller);
61 TraceContext.Instance.EnterLogicalOperation(caller,false);
58 try {
62 try {
59 func();
63 func();
60 p.Resolve();
64 p.Resolve();
61 } catch (Exception e) {
65 } catch (Exception e) {
62 p.Reject(e);
66 p.Reject(e);
67 } finally {
68 TraceContext.Instance.Leave();
63 }
69 }
64 });
70 });
65 worker.IsBackground = true;
71 worker.IsBackground = true;
66 worker.Start();
72 worker.Start();
67
73
68 return p;
74 return p;
69 }
75 }
70 }
76 }
71 }
77 }
@@ -1,204 +1,199
1 using System;
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading;
2 using System.Threading;
6 using System.Diagnostics;
7
3
8 namespace Implab.Parallels {
4 namespace Implab.Parallels {
9 public abstract class DispatchPool<TUnit> : IDisposable {
5 public abstract class DispatchPool<TUnit> : IDisposable {
10 readonly int m_minThreadsLimit;
6 readonly int m_minThreadsLimit;
11 readonly int m_maxThreadsLimit;
7 readonly int m_maxThreadsLimit;
12 readonly int m_releaseTimeout = 1000; // the timeout while the working thread will wait for the new tasks before exit
8 readonly int m_releaseTimeout = 1000; // the timeout while the working thread will wait for the new tasks before exit
13
9
14 int m_threads = 0; // the current size of the pool
10 int m_threads = 0; // the current size of the pool
15 int m_maxRunningThreads = 0; // the meximum reached size of the pool
11 int m_maxRunningThreads = 0; // the meximum reached size of the pool
16 int m_exit = 0; // the pool is going to shutdown, all unused workers are released
12 int m_exit = 0; // the pool is going to shutdown, all unused workers are released
17
13
18 readonly object m_signal = new object(); // used to pulse waiting threads
14 readonly object m_signal = new object(); // used to pulse waiting threads
19
15
20 protected DispatchPool(int min, int max) {
16 protected DispatchPool(int min, int max) {
21 if (min < 0)
17 if (min < 0)
22 throw new ArgumentOutOfRangeException("min");
18 throw new ArgumentOutOfRangeException("min");
23 if (max <= 0)
19 if (max <= 0)
24 throw new ArgumentOutOfRangeException("max");
20 throw new ArgumentOutOfRangeException("max");
25
21
26 if (min > max)
22 if (min > max)
27 min = max;
23 min = max;
28 m_minThreadsLimit = min;
24 m_minThreadsLimit = min;
29 m_maxThreadsLimit = max;
25 m_maxThreadsLimit = max;
30 }
26 }
31
27
32 protected DispatchPool(int threads)
28 protected DispatchPool(int threads)
33 : this(threads, threads) {
29 : this(threads, threads) {
34 }
30 }
35
31
36 protected DispatchPool() {
32 protected DispatchPool() {
37 int maxThreads, maxCP;
33 int maxThreads, maxCP;
38 ThreadPool.GetMaxThreads(out maxThreads, out maxCP);
34 ThreadPool.GetMaxThreads(out maxThreads, out maxCP);
39
35
40 m_minThreadsLimit = 0;
36 m_minThreadsLimit = 0;
41 m_maxThreadsLimit = maxThreads;
37 m_maxThreadsLimit = maxThreads;
42 }
38 }
43
39
44 protected void InitPool() {
40 protected void InitPool() {
45 for (int i = 0; i < m_minThreadsLimit; i++)
41 for (int i = 0; i < m_minThreadsLimit; i++)
46 StartWorker();
42 StartWorker();
47 }
43 }
48
44
49 public int PoolSize {
45 public int PoolSize {
50 get {
46 get {
51 Thread.MemoryBarrier();
47 Thread.MemoryBarrier();
52 return m_threads;
48 return m_threads;
53 }
49 }
54 }
50 }
55
51
56 public int MaxRunningThreads {
52 public int MaxRunningThreads {
57 get {
53 get {
58 Thread.MemoryBarrier();
54 Thread.MemoryBarrier();
59 return m_maxRunningThreads;
55 return m_maxRunningThreads;
60 }
56 }
61 }
57 }
62
58
63 protected bool IsDisposed {
59 protected bool IsDisposed {
64 get {
60 get {
65 Thread.MemoryBarrier();
61 Thread.MemoryBarrier();
66 return m_exit == 1;
62 return m_exit == 1;
67 }
63 }
68 }
64 }
69
65
70 protected abstract bool TryDequeue(out TUnit unit);
66 protected abstract bool TryDequeue(out TUnit unit);
71
67
72 bool Dequeue(out TUnit unit, int timeout) {
68 bool Dequeue(out TUnit unit, int timeout) {
73 int ts = Environment.TickCount;
69 int ts = Environment.TickCount;
74 if (TryDequeue(out unit))
70 if (TryDequeue(out unit))
75 return true;
71 return true;
76 lock (m_signal) {
72 lock (m_signal) {
77 while (!TryDequeue(out unit) && m_exit == 0)
73 while (!TryDequeue(out unit) && m_exit == 0)
78 if(!Monitor.Wait(m_signal, Math.Max(0, ts + timeout - Environment.TickCount))) {
74 if(!Monitor.Wait(m_signal, Math.Max(0, ts + timeout - Environment.TickCount))) {
79 // timeout
75 // timeout
80 return false;
76 return false;
81 }
77 }
82 // queue item or terminate
78 // queue item or terminate
83 Monitor.Pulse(m_signal);
79 Monitor.Pulse(m_signal);
84 if (m_exit == 1)
80 if (m_exit == 1)
85 return false;
81 return false;
86 }
82 }
87 return true;
83 return true;
88 }
84 }
89
85
90 protected void SignalThread() {
86 protected void SignalThread() {
91 lock (m_signal) {
87 lock (m_signal) {
92 Monitor.Pulse(m_signal);
88 Monitor.Pulse(m_signal);
93 }
89 }
94 }
90 }
95
91
96 #region thread slots traits
92 #region thread slots traits
97
93
98 bool AllocateThreadSlot() {
94 bool AllocateThreadSlot() {
99 int current;
95 int current;
100 // use spins to allocate slot for the new thread
96 // use spins to allocate slot for the new thread
101 do {
97 do {
102 current = m_threads;
98 current = m_threads;
103 if (current >= m_maxThreadsLimit || m_exit == 1)
99 if (current >= m_maxThreadsLimit || m_exit == 1)
104 // no more slots left or the pool has been disposed
100 // no more slots left or the pool has been disposed
105 return false;
101 return false;
106 } while (current != Interlocked.CompareExchange(ref m_threads, current + 1, current));
102 } while (current != Interlocked.CompareExchange(ref m_threads, current + 1, current));
107
103
108 UpdateMaxThreads(current + 1);
104 UpdateMaxThreads(current + 1);
109
105
110 return true;
106 return true;
111 }
107 }
112
108
113 bool AllocateThreadSlot(int desired) {
109 bool AllocateThreadSlot(int desired) {
114 if (desired - 1 != Interlocked.CompareExchange(ref m_threads, desired, desired - 1))
110 if (desired - 1 != Interlocked.CompareExchange(ref m_threads, desired, desired - 1))
115 return false;
111 return false;
116
112
117 UpdateMaxThreads(desired);
113 UpdateMaxThreads(desired);
118
114
119 return true;
115 return true;
120 }
116 }
121
117
122 bool ReleaseThreadSlot(out bool last) {
118 bool ReleaseThreadSlot(out bool last) {
123 last = false;
119 last = false;
124 int current;
120 int current;
125 // use spins to release slot for the new thread
121 // use spins to release slot for the new thread
126 Thread.MemoryBarrier();
122 Thread.MemoryBarrier();
127 do {
123 do {
128 current = m_threads;
124 current = m_threads;
129 if (current <= m_minThreadsLimit && m_exit == 0)
125 if (current <= m_minThreadsLimit && m_exit == 0)
130 // the thread is reserved
126 // the thread is reserved
131 return false;
127 return false;
132 } while (current != Interlocked.CompareExchange(ref m_threads, current - 1, current));
128 } while (current != Interlocked.CompareExchange(ref m_threads, current - 1, current));
133
129
134 last = (current == 1);
130 last = (current == 1);
135
131
136 return true;
132 return true;
137 }
133 }
138
134
139 void UpdateMaxThreads(int count) {
135 void UpdateMaxThreads(int count) {
140 int max;
136 int max;
141 do {
137 do {
142 max = m_maxRunningThreads;
138 max = m_maxRunningThreads;
143 if (max >= count)
139 if (max >= count)
144 break;
140 break;
145 } while(max != Interlocked.CompareExchange(ref m_maxRunningThreads, count, max));
141 } while(max != Interlocked.CompareExchange(ref m_maxRunningThreads, count, max));
146 }
142 }
147
143
148 #endregion
144 #endregion
149
145
150 protected bool StartWorker() {
146 protected bool StartWorker() {
151 if (AllocateThreadSlot()) {
147 if (AllocateThreadSlot()) {
152 // slot successfully allocated
148 // slot successfully allocated
153 var worker = new Thread(this.Worker);
149 var worker = new Thread(Worker);
154 worker.IsBackground = true;
150 worker.IsBackground = true;
155 worker.Start();
151 worker.Start();
156
152
157 return true;
153 return true;
158 } else {
159 return false;
160 }
154 }
155 return false;
161 }
156 }
162
157
163 protected abstract void InvokeUnit(TUnit unit);
158 protected abstract void InvokeUnit(TUnit unit);
164
159
165 protected virtual void Worker() {
160 protected virtual void Worker() {
166 TUnit unit;
161 TUnit unit;
167 bool last;
162 bool last;
168 do {
163 do {
169 while (Dequeue(out unit, m_releaseTimeout)) {
164 while (Dequeue(out unit, m_releaseTimeout)) {
170 InvokeUnit(unit);
165 InvokeUnit(unit);
171 }
166 }
172 if(!ReleaseThreadSlot(out last))
167 if(!ReleaseThreadSlot(out last))
173 continue;
168 continue;
174 // queue may be not empty
169 // queue may be not empty
175 if (last && TryDequeue(out unit)) {
170 if (last && TryDequeue(out unit)) {
176 InvokeUnit(unit);
171 InvokeUnit(unit);
177 if (AllocateThreadSlot(1))
172 if (AllocateThreadSlot(1))
178 continue;
173 continue;
179 // we can safely exit since pool is alive
174 // we can safely exit since pool is alive
180 }
175 }
181 break;
176 break;
182 } while(true);
177 } while(true);
183 }
178 }
184
179
185
180
186 protected virtual void Dispose(bool disposing) {
181 protected virtual void Dispose(bool disposing) {
187 if (disposing) {
182 if (disposing) {
188 if (0 == Interlocked.CompareExchange(ref m_exit, 1, 0)) { // implies memory barrier
183 if (0 == Interlocked.CompareExchange(ref m_exit, 1, 0)) { // implies memory barrier
189 // wake sleeping threads
184 // wake sleeping threads
190 SignalThread();
185 SignalThread();
191 GC.SuppressFinalize(this);
186 GC.SuppressFinalize(this);
192 }
187 }
193 }
188 }
194 }
189 }
195
190
196 public void Dispose() {
191 public void Dispose() {
197 Dispose(true);
192 Dispose(true);
198 }
193 }
199
194
200 ~DispatchPool() {
195 ~DispatchPool() {
201 Dispose(false);
196 Dispose(false);
202 }
197 }
203 }
198 }
204 }
199 }
@@ -1,89 +1,82
1 using System;
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading;
2 using System.Threading;
6 using System.Diagnostics;
3 using System.Diagnostics;
7 using Implab.Diagnostics;
4 using Implab.Diagnostics;
8
5
9 namespace Implab.Parallels {
6 namespace Implab.Parallels {
10 public class WorkerPool : DispatchPool<Action> {
7 public class WorkerPool : DispatchPool<Action> {
11
8
12 MTQueue<Action> m_queue = new MTQueue<Action>();
9 MTQueue<Action> m_queue = new MTQueue<Action>();
13 int m_queueLength = 0;
10 int m_queueLength = 0;
14 readonly int m_threshold = 1;
11 readonly int m_threshold = 1;
15 int m_workers = 0;
16
12
17 public WorkerPool(int minThreads, int maxThreads, int threshold)
13 public WorkerPool(int minThreads, int maxThreads, int threshold)
18 : base(minThreads, maxThreads) {
14 : base(minThreads, maxThreads) {
19 m_threshold = threshold;
15 m_threshold = threshold;
20 m_workers = minThreads;
21 InitPool();
16 InitPool();
22 }
17 }
23
18
24 public WorkerPool(int minThreads, int maxThreads) :
19 public WorkerPool(int minThreads, int maxThreads) :
25 base(minThreads, maxThreads) {
20 base(minThreads, maxThreads) {
26 m_workers = minThreads;
27 InitPool();
21 InitPool();
28 }
22 }
29
23
30 public WorkerPool(int threads)
24 public WorkerPool(int threads)
31 : base(threads) {
25 : base(threads) {
32 m_workers = threads;
33 InitPool();
26 InitPool();
34 }
27 }
35
28
36 public WorkerPool()
29 public WorkerPool() {
37 : base() {
38 InitPool();
30 InitPool();
39 }
31 }
40
32
41 public Promise<T> Invoke<T>(Func<T> task) {
33 public Promise<T> Invoke<T>(Func<T> task) {
42 if (task == null)
34 if (task == null)
43 throw new ArgumentNullException("task");
35 throw new ArgumentNullException("task");
44 if (IsDisposed)
36 if (IsDisposed)
45 throw new ObjectDisposedException(ToString());
37 throw new ObjectDisposedException(ToString());
46
38
47 var promise = new Promise<T>();
39 var promise = new Promise<T>();
48
40
49 var caller = TraceContext.Snapshot();
41 var lop = TraceContext.Instance.CurrentOperation;
50
42
51 EnqueueTask(delegate() {
43 EnqueueTask(delegate() {
52 caller.Invoke(delegate() {
44 TraceContext.Instance.EnterLogicalOperation(lop, false);
53 try {
45 try {
54 promise.Resolve(task());
46 promise.Resolve(task());
55 } catch (Exception e) {
47 } catch (Exception e) {
56 promise.Reject(e);
48 promise.Reject(e);
57 }
49 } finally {
58 });
50 TraceContext.Instance.Leave();
51 }
59 });
52 });
60
53
61 return promise;
54 return promise;
62 }
55 }
63
56
64 protected void EnqueueTask(Action unit) {
57 protected void EnqueueTask(Action unit) {
65 Debug.Assert(unit != null);
58 Debug.Assert(unit != null);
66 var len = Interlocked.Increment(ref m_queueLength);
59 var len = Interlocked.Increment(ref m_queueLength);
67 m_queue.Enqueue(unit);
60 m_queue.Enqueue(unit);
68
61
69 if (len > m_threshold * PoolSize) {
62 if (len > m_threshold * PoolSize) {
70 StartWorker();
63 StartWorker();
71 }
64 }
72
65
73 SignalThread();
66 SignalThread();
74 }
67 }
75
68
76 protected override bool TryDequeue(out Action unit) {
69 protected override bool TryDequeue(out Action unit) {
77 if (m_queue.TryDequeue(out unit)) {
70 if (m_queue.TryDequeue(out unit)) {
78 Interlocked.Decrement(ref m_queueLength);
71 Interlocked.Decrement(ref m_queueLength);
79 return true;
72 return true;
80 }
73 }
81 return false;
74 return false;
82 }
75 }
83
76
84 protected override void InvokeUnit(Action unit) {
77 protected override void InvokeUnit(Action unit) {
85 unit();
78 unit();
86 }
79 }
87
80
88 }
81 }
89 }
82 }
General Comments 0
You need to be logged in to leave comments. Login now