##// END OF EJS Templates
Interactive tracing...
cin -
r48:d9d794b61bb9 interactive logger
parent child
Show More
@@ -1,107 +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: Disposable
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
18
18 readonly IPromiseBase m_guiFinished;
19 readonly IPromiseBase m_guiFinished;
19 readonly Promise<object> m_guiStarted = new Promise<object>();
20
21 readonly IPromiseBase m_workerFinished = new Promise<object>();
20 readonly IPromiseBase m_workerFinished = new Promise<object>();
22
21
23 readonly MTQueue<TraceViewItem> m_queue = new MTQueue<TraceViewItem>();
22 readonly MTQueue<TraceViewItem> m_queue = new MTQueue<TraceViewItem>();
24 readonly AutoResetEvent m_queueEvent = new AutoResetEvent(false);
23 readonly AutoResetEvent m_queueEvent = new AutoResetEvent(false);
25
24
26 int m_queueLength;
25 int m_queueLength;
27 bool m_exitPending;
26 bool m_exitPending;
28
27
29 readonly object m_pauseLock = new object();
28 readonly object m_pauseLock = new object();
30 bool m_paused;
29 bool m_paused;
31 readonly ManualResetEvent m_pauseEvent = new ManualResetEvent(true);
30 readonly ManualResetEvent m_pauseEvent = new ManualResetEvent(true);
32
31
33 public InteractiveListener() {
32 public InteractiveListener(bool global) : base(global) {
34 m_guiFinished = AsyncPool.InvokeNewThread(() => {
33 m_guiFinished = AsyncPool.InvokeNewThread(GuiThread);
35 GuiThread();
34 m_workerFinished = AsyncPool.InvokeNewThread(QueueThread);
36 return 0;
37 });
38
35
39 m_guiStarted.Join();
36 m_guiStarted.Join();
40 }
37 }
41
38
42 void GuiThread() {
39 void GuiThread() {
43 m_form = new TraceForm(); // will create SynchronizationContext
40 m_form = new TraceForm(); // will create SynchronizationContext
41
42 m_form.PauseEvents += (s,a) => Pause();
43 m_form.ResumeEvents += (s, a) => Resume();
44
44 m_syncGuiThread = SynchronizationContext.Current;
45 m_syncGuiThread = SynchronizationContext.Current;
45 m_guiStarted.Resolve();
46 m_guiStarted.Resolve();
46 Application.Run();
47 Application.Run();
47 }
48 }
48
49
49 void QueueThread() {
50 void QueueThread() {
50 while (!m_exitPending) {
51 while (!m_exitPending) {
51 if (m_paused)
52 if (m_paused)
52 m_pauseEvent.WaitOne();
53 m_pauseEvent.WaitOne();
53
54
54 TraceViewItem item;
55 TraceViewItem item;
55 if (m_queue.TryDequeue(out item)) {
56 if (m_queue.TryDequeue(out item)) {
56 Interlocked.Decrement(ref m_queueLength);
57 Interlocked.Decrement(ref m_queueLength);
57
58
58 m_syncGuiThread.Send(x => m_form.AddTraceEvent(item),null);
59 m_syncGuiThread.Send(x => m_form.AddTraceEvent(item),null);
59 } else {
60 } else {
60 m_queueEvent.WaitOne();
61 m_queueEvent.WaitOne();
61 }
62 }
62 }
63 }
63 }
64 }
64
65
65 public void Pause() {
66 public void Pause() {
66 // for consistency we need to set this properties atomically
67 // for consistency we need to set this properties atomically
67 lock (m_pauseLock) {
68 lock (m_pauseLock) {
68 m_pauseEvent.Reset();
69 m_pauseEvent.Reset();
69 m_paused = true;
70 m_paused = true;
70 }
71 }
71 }
72 }
72
73
73 public void Resume() {
74 public void Resume() {
74 // for consistency we need to set this properties atomically
75 // for consistency we need to set this properties atomically
75 lock (m_pauseLock) {
76 lock (m_pauseLock) {
76 m_paused = false;
77 m_paused = false;
77 m_pauseEvent.Set();
78 m_pauseEvent.Set();
78 }
79 }
79 }
80 }
80
81
81 void Enqueue(TraceViewItem item) {
82 void Enqueue(TraceViewItem item) {
82 m_queue.Enqueue(item);
83 m_queue.Enqueue(item);
83 if (Interlocked.Increment(ref m_queueLength) == 1)
84 if (Interlocked.Increment(ref m_queueLength) == 1)
84 m_queueEvent.Set();
85 m_queueEvent.Set();
85 }
86 }
86
87
87 public void ShowForm() {
88 public void ShowForm() {
88 m_syncGuiThread.Post(x => m_form.Show(), null);
89 m_syncGuiThread.Post(x => m_form.Show(), null);
89 }
90 }
90
91
91 public void HideForm() {
92 public void HideForm() {
92 m_syncGuiThread.Post(x => m_form.Hide(), null);
93 m_syncGuiThread.Post(x => m_form.Hide(), null);
93 }
94 }
94
95
95 void Terminate() {
96 void Terminate() {
97 m_exitPending = true;
98 Resume();
96 m_syncGuiThread.Post(x => Application.ExitThread(), null);
99 m_syncGuiThread.Post(x => Application.ExitThread(), null);
97 }
100 }
98
101
99 protected override void Dispose(bool disposing) {
102 protected override void Dispose(bool disposing) {
100 if (disposing) {
103 if (disposing) {
101 Terminate();
104 Terminate();
102 m_guiFinished.Join();
105 m_guiFinished.Join();
103 }
106 }
104 base.Dispose(disposing);
107 base.Dispose(disposing);
105 }
108 }
109
110 protected override void WriteEntry(TraceContext context, EventText text, string channel) {
111 var item = new TraceViewItem {
112 Indent = text.indent,
113 Message = text.content,
114 Thread = context.ThreadId,
115 Channel = channel,
116 Timestamp = Environment.TickCount
117 };
118
119 Enqueue(item);
106 }
120 }
107 }
121 }
122 }
@@ -1,122 +1,134
1 namespace Implab.Diagnostics.Interactive {
1 namespace Implab.Diagnostics.Interactive {
2 partial class TraceForm {
2 partial class TraceForm {
3 /// <summary>
3 /// <summary>
4 /// Required designer variable.
4 /// Required designer variable.
5 /// </summary>
5 /// </summary>
6 private System.ComponentModel.IContainer components = null;
6 private System.ComponentModel.IContainer components = null;
7
7
8 /// <summary>
8 /// <summary>
9 /// Clean up any resources being used.
9 /// Clean up any resources being used.
10 /// </summary>
10 /// </summary>
11 /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
11 /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
12 protected override void Dispose(bool disposing) {
12 protected override void Dispose(bool disposing) {
13 if (disposing && (components != null)) {
13 if (disposing && (components != null)) {
14 components.Dispose();
14 components.Dispose();
15 }
15 }
16 base.Dispose(disposing);
16 base.Dispose(disposing);
17 }
17 }
18
18
19 #region Windows Form Designer generated code
19 #region Windows Form Designer generated code
20
20
21 /// <summary>
21 /// <summary>
22 /// Required method for Designer support - do not modify
22 /// Required method for Designer support - do not modify
23 /// the contents of this method with the code editor.
23 /// the contents of this method with the code editor.
24 /// </summary>
24 /// </summary>
25 private void InitializeComponent() {
25 private void InitializeComponent() {
26 this.components = new System.ComponentModel.Container();
26 this.components = new System.ComponentModel.Container();
27 System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle();
27 System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle();
28 System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle3 = new System.Windows.Forms.DataGridViewCellStyle();
28 System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle3 = new System.Windows.Forms.DataGridViewCellStyle();
29 System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle2 = new System.Windows.Forms.DataGridViewCellStyle();
29 System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle2 = new System.Windows.Forms.DataGridViewCellStyle();
30 this.eventsDataGrid = new System.Windows.Forms.DataGridView();
30 this.eventsDataGrid = new System.Windows.Forms.DataGridView();
31 this.traceViewItemBindingSource = new System.Windows.Forms.BindingSource(this.components);
31 this.traceViewItemBindingSource = new System.Windows.Forms.BindingSource(this.components);
32 this.threadDataGridViewTextBoxColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
32 this.threadDataGridViewTextBoxColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
33 this.Channel = new System.Windows.Forms.DataGridViewTextBoxColumn();
33 this.messageDataGridViewTextBoxColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
34 this.messageDataGridViewTextBoxColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
34 ((System.ComponentModel.ISupportInitialize)(this.eventsDataGrid)).BeginInit();
35 ((System.ComponentModel.ISupportInitialize)(this.eventsDataGrid)).BeginInit();
35 ((System.ComponentModel.ISupportInitialize)(this.traceViewItemBindingSource)).BeginInit();
36 ((System.ComponentModel.ISupportInitialize)(this.traceViewItemBindingSource)).BeginInit();
36 this.SuspendLayout();
37 this.SuspendLayout();
37 //
38 //
38 // eventsDataGrid
39 // eventsDataGrid
39 //
40 //
40 this.eventsDataGrid.AllowUserToAddRows = false;
41 this.eventsDataGrid.AllowUserToAddRows = false;
41 this.eventsDataGrid.AllowUserToDeleteRows = false;
42 this.eventsDataGrid.AllowUserToDeleteRows = false;
42 this.eventsDataGrid.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
43 this.eventsDataGrid.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
43 | System.Windows.Forms.AnchorStyles.Left)
44 | System.Windows.Forms.AnchorStyles.Left)
44 | System.Windows.Forms.AnchorStyles.Right)));
45 | System.Windows.Forms.AnchorStyles.Right)));
45 this.eventsDataGrid.AutoGenerateColumns = false;
46 this.eventsDataGrid.AutoGenerateColumns = false;
46 this.eventsDataGrid.BackgroundColor = System.Drawing.SystemColors.Window;
47 this.eventsDataGrid.BackgroundColor = System.Drawing.SystemColors.Window;
47 dataGridViewCellStyle1.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
48 dataGridViewCellStyle1.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
48 dataGridViewCellStyle1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
49 dataGridViewCellStyle1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
49 dataGridViewCellStyle1.Font = new System.Drawing.Font("Lucida Console", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
50 dataGridViewCellStyle1.Font = new System.Drawing.Font("Lucida Console", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
50 dataGridViewCellStyle1.ForeColor = System.Drawing.SystemColors.WindowText;
51 dataGridViewCellStyle1.ForeColor = System.Drawing.SystemColors.WindowText;
51 dataGridViewCellStyle1.SelectionBackColor = System.Drawing.SystemColors.Highlight;
52 dataGridViewCellStyle1.SelectionBackColor = System.Drawing.SystemColors.Highlight;
52 dataGridViewCellStyle1.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
53 dataGridViewCellStyle1.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
53 dataGridViewCellStyle1.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
54 dataGridViewCellStyle1.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
54 this.eventsDataGrid.ColumnHeadersDefaultCellStyle = dataGridViewCellStyle1;
55 this.eventsDataGrid.ColumnHeadersDefaultCellStyle = dataGridViewCellStyle1;
55 this.eventsDataGrid.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
56 this.eventsDataGrid.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
56 this.eventsDataGrid.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
57 this.eventsDataGrid.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
57 this.threadDataGridViewTextBoxColumn,
58 this.threadDataGridViewTextBoxColumn,
59 this.Channel,
58 this.messageDataGridViewTextBoxColumn});
60 this.messageDataGridViewTextBoxColumn});
59 this.eventsDataGrid.DataSource = this.traceViewItemBindingSource;
61 this.eventsDataGrid.DataSource = this.traceViewItemBindingSource;
60 dataGridViewCellStyle3.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
62 dataGridViewCellStyle3.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
61 dataGridViewCellStyle3.BackColor = System.Drawing.SystemColors.Window;
63 dataGridViewCellStyle3.BackColor = System.Drawing.SystemColors.Window;
62 dataGridViewCellStyle3.Font = new System.Drawing.Font("Lucida Console", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
64 dataGridViewCellStyle3.Font = new System.Drawing.Font("Lucida Console", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
63 dataGridViewCellStyle3.ForeColor = System.Drawing.SystemColors.ControlText;
65 dataGridViewCellStyle3.ForeColor = System.Drawing.SystemColors.ControlText;
64 dataGridViewCellStyle3.SelectionBackColor = System.Drawing.SystemColors.Highlight;
66 dataGridViewCellStyle3.SelectionBackColor = System.Drawing.SystemColors.Highlight;
65 dataGridViewCellStyle3.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
67 dataGridViewCellStyle3.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
66 dataGridViewCellStyle3.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
68 dataGridViewCellStyle3.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
67 this.eventsDataGrid.DefaultCellStyle = dataGridViewCellStyle3;
69 this.eventsDataGrid.DefaultCellStyle = dataGridViewCellStyle3;
68 this.eventsDataGrid.Location = new System.Drawing.Point(12, 12);
70 this.eventsDataGrid.Location = new System.Drawing.Point(12, 12);
69 this.eventsDataGrid.Name = "eventsDataGrid";
71 this.eventsDataGrid.Name = "eventsDataGrid";
70 this.eventsDataGrid.ReadOnly = true;
72 this.eventsDataGrid.ReadOnly = true;
71 this.eventsDataGrid.RowHeadersWidth = 17;
73 this.eventsDataGrid.RowHeadersWidth = 17;
72 this.eventsDataGrid.RowTemplate.Resizable = System.Windows.Forms.DataGridViewTriState.False;
74 this.eventsDataGrid.RowTemplate.Resizable = System.Windows.Forms.DataGridViewTriState.False;
73 this.eventsDataGrid.Size = new System.Drawing.Size(939, 480);
75 this.eventsDataGrid.Size = new System.Drawing.Size(939, 480);
74 this.eventsDataGrid.TabIndex = 1;
76 this.eventsDataGrid.TabIndex = 1;
75 this.eventsDataGrid.CellFormatting += new System.Windows.Forms.DataGridViewCellFormattingEventHandler(this.eventsDataGrid_CellFormatting);
77 this.eventsDataGrid.CellFormatting += new System.Windows.Forms.DataGridViewCellFormattingEventHandler(this.eventsDataGrid_CellFormatting);
76 //
78 //
77 // traceViewItemBindingSource
79 // traceViewItemBindingSource
78 //
80 //
79 this.traceViewItemBindingSource.DataSource = typeof(Implab.Diagnostics.Interactive.TraceViewItem);
81 this.traceViewItemBindingSource.DataSource = typeof(Implab.Diagnostics.Interactive.TraceViewItem);
80 //
82 //
81 // threadDataGridViewTextBoxColumn
83 // threadDataGridViewTextBoxColumn
82 //
84 //
83 this.threadDataGridViewTextBoxColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.AllCellsExceptHeader;
85 this.threadDataGridViewTextBoxColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.AllCellsExceptHeader;
84 this.threadDataGridViewTextBoxColumn.DataPropertyName = "Thread";
86 this.threadDataGridViewTextBoxColumn.DataPropertyName = "Thread";
85 this.threadDataGridViewTextBoxColumn.HeaderText = "TID";
87 this.threadDataGridViewTextBoxColumn.HeaderText = "TID";
86 this.threadDataGridViewTextBoxColumn.Name = "threadDataGridViewTextBoxColumn";
88 this.threadDataGridViewTextBoxColumn.Name = "threadDataGridViewTextBoxColumn";
87 this.threadDataGridViewTextBoxColumn.ReadOnly = true;
89 this.threadDataGridViewTextBoxColumn.ReadOnly = true;
88 this.threadDataGridViewTextBoxColumn.Width = 5;
90 this.threadDataGridViewTextBoxColumn.Width = 5;
89 //
91 //
92 // Channel
93 //
94 this.Channel.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.DisplayedCells;
95 this.Channel.DataPropertyName = "Channel";
96 this.Channel.HeaderText = "Channel";
97 this.Channel.Name = "Channel";
98 this.Channel.ReadOnly = true;
99 this.Channel.Width = 79;
100 //
90 // messageDataGridViewTextBoxColumn
101 // messageDataGridViewTextBoxColumn
91 //
102 //
92 this.messageDataGridViewTextBoxColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
103 this.messageDataGridViewTextBoxColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
93 this.messageDataGridViewTextBoxColumn.DataPropertyName = "FormattedMessage";
104 this.messageDataGridViewTextBoxColumn.DataPropertyName = "FormattedMessage";
94 dataGridViewCellStyle2.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
105 dataGridViewCellStyle2.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
95 this.messageDataGridViewTextBoxColumn.DefaultCellStyle = dataGridViewCellStyle2;
106 this.messageDataGridViewTextBoxColumn.DefaultCellStyle = dataGridViewCellStyle2;
96 this.messageDataGridViewTextBoxColumn.HeaderText = "Message";
107 this.messageDataGridViewTextBoxColumn.HeaderText = "Message";
97 this.messageDataGridViewTextBoxColumn.Name = "messageDataGridViewTextBoxColumn";
108 this.messageDataGridViewTextBoxColumn.Name = "messageDataGridViewTextBoxColumn";
98 this.messageDataGridViewTextBoxColumn.ReadOnly = true;
109 this.messageDataGridViewTextBoxColumn.ReadOnly = true;
99 //
110 //
100 // TraceForm
111 // TraceForm
101 //
112 //
102 this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
113 this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
103 this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
114 this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
104 this.ClientSize = new System.Drawing.Size(963, 504);
115 this.ClientSize = new System.Drawing.Size(963, 504);
105 this.Controls.Add(this.eventsDataGrid);
116 this.Controls.Add(this.eventsDataGrid);
106 this.Name = "TraceForm";
117 this.Name = "TraceForm";
107 this.Text = "TraceForm";
118 this.Text = "TraceForm";
108 ((System.ComponentModel.ISupportInitialize)(this.eventsDataGrid)).EndInit();
119 ((System.ComponentModel.ISupportInitialize)(this.eventsDataGrid)).EndInit();
109 ((System.ComponentModel.ISupportInitialize)(this.traceViewItemBindingSource)).EndInit();
120 ((System.ComponentModel.ISupportInitialize)(this.traceViewItemBindingSource)).EndInit();
110 this.ResumeLayout(false);
121 this.ResumeLayout(false);
111
122
112 }
123 }
113
124
114 #endregion
125 #endregion
115
126
116 private System.Windows.Forms.DataGridView eventsDataGrid;
127 private System.Windows.Forms.DataGridView eventsDataGrid;
117 private System.Windows.Forms.BindingSource traceViewItemBindingSource;
128 private System.Windows.Forms.BindingSource traceViewItemBindingSource;
118 private System.Windows.Forms.DataGridViewTextBoxColumn threadDataGridViewTextBoxColumn;
129 private System.Windows.Forms.DataGridViewTextBoxColumn threadDataGridViewTextBoxColumn;
130 private System.Windows.Forms.DataGridViewTextBoxColumn Channel;
119 private System.Windows.Forms.DataGridViewTextBoxColumn messageDataGridViewTextBoxColumn;
131 private System.Windows.Forms.DataGridViewTextBoxColumn messageDataGridViewTextBoxColumn;
120
132
121 }
133 }
122 } No newline at end of file
134 }
@@ -1,58 +1,53
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.ComponentModel;
3 using System.ComponentModel;
4 using System.Data;
4 using System.Data;
5 using System.Drawing;
5 using System.Drawing;
6 using System.Linq;
6 using System.Linq;
7 using System.Text;
7 using System.Text;
8 using System.Threading.Tasks;
8 using System.Threading.Tasks;
9 using System.Windows.Forms;
9 using System.Windows.Forms;
10
10
11 namespace Implab.Diagnostics.Interactive {
11 namespace Implab.Diagnostics.Interactive {
12 public partial class TraceForm : Form {
12 public partial class TraceForm : Form {
13 readonly Dictionary<int, Color> m_threadColors = new Dictionary<int,Color>();
13 readonly Dictionary<int, Color> m_threadColors = new Dictionary<int,Color>();
14 readonly Random m_rand = new Random();
14 readonly Random m_rand = new Random();
15
15
16 public event EventHandler PauseEvents;
17
18 public event EventHandler ResumeEvents;
19
16 public TraceForm() {
20 public TraceForm() {
17 InitializeComponent();
21 InitializeComponent();
18
19 }
22 }
20
23
21 protected override void OnFormClosing(FormClosingEventArgs e) {
24 protected override void OnFormClosing(FormClosingEventArgs e) {
22 base.OnFormClosing(e);
25 base.OnFormClosing(e);
23 if (!e.Cancel && e.CloseReason == CloseReason.UserClosing) {
26 if (!e.Cancel && e.CloseReason == CloseReason.UserClosing) {
24 e.Cancel = true;
27 e.Cancel = true;
25 Hide();
28 Hide();
26 }
29 }
27 }
30 }
28
31
29 public void AddTraceEvent(int indent, int thread, string message) {
30 traceViewItemBindingSource.Add(new TraceViewItem {
31 Indent = indent,
32 Thread = thread,
33 Message = message,
34 Timestamp = Environment.TickCount
35 });
36
37 }
38
39 public void AddTraceEvent(TraceViewItem item) {
32 public void AddTraceEvent(TraceViewItem item) {
40 traceViewItemBindingSource.Add(item);
33 traceViewItemBindingSource.Add(item);
34 eventsDataGrid.FirstDisplayedScrollingRowIndex = eventsDataGrid.RowCount - 1;
41 }
35 }
42
36
43 Color GetThreadColor(int thread) {
37 Color GetThreadColor(int thread) {
44 Color result;
38 Color result;
45 if (!m_threadColors.TryGetValue(thread, out result)) {
39 if (!m_threadColors.TryGetValue(thread, out result)) {
46 result = Color.FromArgb(m_rand.Next(4)*64, m_rand.Next(4)*64, m_rand.Next(4)*64);
40 result = Color.FromArgb(m_rand.Next(4)*64, m_rand.Next(4)*64, m_rand.Next(4)*64);
47 m_threadColors[thread] = result;
41 m_threadColors[thread] = result;
48 }
42 }
49 return result;
43 return result;
50 }
44 }
51
45
52 private void eventsDataGrid_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e) {
46 private void eventsDataGrid_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e) {
53 var data = (TraceViewItem)traceViewItemBindingSource[e.RowIndex];
47 var data = (TraceViewItem)traceViewItemBindingSource[e.RowIndex];
48 if (e.ColumnIndex == messageDataGridViewTextBoxColumn.Index)
54 e.CellStyle.Padding = new Padding(data.Indent * 10,0,0,0);
49 e.CellStyle.Padding = new Padding(data.Indent * 10,0,0,0);
55 e.CellStyle.ForeColor = GetThreadColor(data.Thread);
50 e.CellStyle.ForeColor = GetThreadColor(data.Thread);
56 }
51 }
57 }
52 }
58 }
53 }
@@ -1,123 +1,126
1 ο»Ώ<?xml version="1.0" encoding="utf-8"?>
1 ο»Ώ<?xml version="1.0" encoding="utf-8"?>
2 <root>
2 <root>
3 <!--
3 <!--
4 Microsoft ResX Schema
4 Microsoft ResX Schema
5
5
6 Version 2.0
6 Version 2.0
7
7
8 The primary goals of this format is to allow a simple XML format
8 The primary goals of this format is to allow a simple XML format
9 that is mostly human readable. The generation and parsing of the
9 that is mostly human readable. The generation and parsing of the
10 various data types are done through the TypeConverter classes
10 various data types are done through the TypeConverter classes
11 associated with the data types.
11 associated with the data types.
12
12
13 Example:
13 Example:
14
14
15 ... ado.net/XML headers & schema ...
15 ... ado.net/XML headers & schema ...
16 <resheader name="resmimetype">text/microsoft-resx</resheader>
16 <resheader name="resmimetype">text/microsoft-resx</resheader>
17 <resheader name="version">2.0</resheader>
17 <resheader name="version">2.0</resheader>
18 <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
18 <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
19 <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
19 <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
20 <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
20 <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
21 <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
21 <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
22 <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
22 <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
23 <value>[base64 mime encoded serialized .NET Framework object]</value>
23 <value>[base64 mime encoded serialized .NET Framework object]</value>
24 </data>
24 </data>
25 <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
25 <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
26 <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
26 <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
27 <comment>This is a comment</comment>
27 <comment>This is a comment</comment>
28 </data>
28 </data>
29
29
30 There are any number of "resheader" rows that contain simple
30 There are any number of "resheader" rows that contain simple
31 name/value pairs.
31 name/value pairs.
32
32
33 Each data row contains a name, and value. The row also contains a
33 Each data row contains a name, and value. The row also contains a
34 type or mimetype. Type corresponds to a .NET class that support
34 type or mimetype. Type corresponds to a .NET class that support
35 text/value conversion through the TypeConverter architecture.
35 text/value conversion through the TypeConverter architecture.
36 Classes that don't support this are serialized and stored with the
36 Classes that don't support this are serialized and stored with the
37 mimetype set.
37 mimetype set.
38
38
39 The mimetype is used for serialized objects, and tells the
39 The mimetype is used for serialized objects, and tells the
40 ResXResourceReader how to depersist the object. This is currently not
40 ResXResourceReader how to depersist the object. This is currently not
41 extensible. For a given mimetype the value must be set accordingly:
41 extensible. For a given mimetype the value must be set accordingly:
42
42
43 Note - application/x-microsoft.net.object.binary.base64 is the format
43 Note - application/x-microsoft.net.object.binary.base64 is the format
44 that the ResXResourceWriter will generate, however the reader can
44 that the ResXResourceWriter will generate, however the reader can
45 read any of the formats listed below.
45 read any of the formats listed below.
46
46
47 mimetype: application/x-microsoft.net.object.binary.base64
47 mimetype: application/x-microsoft.net.object.binary.base64
48 value : The object must be serialized with
48 value : The object must be serialized with
49 : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
49 : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
50 : and then encoded with base64 encoding.
50 : and then encoded with base64 encoding.
51
51
52 mimetype: application/x-microsoft.net.object.soap.base64
52 mimetype: application/x-microsoft.net.object.soap.base64
53 value : The object must be serialized with
53 value : The object must be serialized with
54 : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
54 : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
55 : and then encoded with base64 encoding.
55 : and then encoded with base64 encoding.
56
56
57 mimetype: application/x-microsoft.net.object.bytearray.base64
57 mimetype: application/x-microsoft.net.object.bytearray.base64
58 value : The object must be serialized into a byte array
58 value : The object must be serialized into a byte array
59 : using a System.ComponentModel.TypeConverter
59 : using a System.ComponentModel.TypeConverter
60 : and then encoded with base64 encoding.
60 : and then encoded with base64 encoding.
61 -->
61 -->
62 <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
62 <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
63 <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
63 <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
64 <xsd:element name="root" msdata:IsDataSet="true">
64 <xsd:element name="root" msdata:IsDataSet="true">
65 <xsd:complexType>
65 <xsd:complexType>
66 <xsd:choice maxOccurs="unbounded">
66 <xsd:choice maxOccurs="unbounded">
67 <xsd:element name="metadata">
67 <xsd:element name="metadata">
68 <xsd:complexType>
68 <xsd:complexType>
69 <xsd:sequence>
69 <xsd:sequence>
70 <xsd:element name="value" type="xsd:string" minOccurs="0" />
70 <xsd:element name="value" type="xsd:string" minOccurs="0" />
71 </xsd:sequence>
71 </xsd:sequence>
72 <xsd:attribute name="name" use="required" type="xsd:string" />
72 <xsd:attribute name="name" use="required" type="xsd:string" />
73 <xsd:attribute name="type" type="xsd:string" />
73 <xsd:attribute name="type" type="xsd:string" />
74 <xsd:attribute name="mimetype" type="xsd:string" />
74 <xsd:attribute name="mimetype" type="xsd:string" />
75 <xsd:attribute ref="xml:space" />
75 <xsd:attribute ref="xml:space" />
76 </xsd:complexType>
76 </xsd:complexType>
77 </xsd:element>
77 </xsd:element>
78 <xsd:element name="assembly">
78 <xsd:element name="assembly">
79 <xsd:complexType>
79 <xsd:complexType>
80 <xsd:attribute name="alias" type="xsd:string" />
80 <xsd:attribute name="alias" type="xsd:string" />
81 <xsd:attribute name="name" type="xsd:string" />
81 <xsd:attribute name="name" type="xsd:string" />
82 </xsd:complexType>
82 </xsd:complexType>
83 </xsd:element>
83 </xsd:element>
84 <xsd:element name="data">
84 <xsd:element name="data">
85 <xsd:complexType>
85 <xsd:complexType>
86 <xsd:sequence>
86 <xsd:sequence>
87 <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
87 <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
88 <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
88 <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
89 </xsd:sequence>
89 </xsd:sequence>
90 <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
90 <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
91 <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
91 <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
92 <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
92 <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
93 <xsd:attribute ref="xml:space" />
93 <xsd:attribute ref="xml:space" />
94 </xsd:complexType>
94 </xsd:complexType>
95 </xsd:element>
95 </xsd:element>
96 <xsd:element name="resheader">
96 <xsd:element name="resheader">
97 <xsd:complexType>
97 <xsd:complexType>
98 <xsd:sequence>
98 <xsd:sequence>
99 <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
99 <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
100 </xsd:sequence>
100 </xsd:sequence>
101 <xsd:attribute name="name" type="xsd:string" use="required" />
101 <xsd:attribute name="name" type="xsd:string" use="required" />
102 </xsd:complexType>
102 </xsd:complexType>
103 </xsd:element>
103 </xsd:element>
104 </xsd:choice>
104 </xsd:choice>
105 </xsd:complexType>
105 </xsd:complexType>
106 </xsd:element>
106 </xsd:element>
107 </xsd:schema>
107 </xsd:schema>
108 <resheader name="resmimetype">
108 <resheader name="resmimetype">
109 <value>text/microsoft-resx</value>
109 <value>text/microsoft-resx</value>
110 </resheader>
110 </resheader>
111 <resheader name="version">
111 <resheader name="version">
112 <value>2.0</value>
112 <value>2.0</value>
113 </resheader>
113 </resheader>
114 <resheader name="reader">
114 <resheader name="reader">
115 <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
115 <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
116 </resheader>
116 </resheader>
117 <resheader name="writer">
117 <resheader name="writer">
118 <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
118 <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
119 </resheader>
119 </resheader>
120 <metadata name="Channel.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
121 <value>True</value>
122 </metadata>
120 <metadata name="traceViewItemBindingSource.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
123 <metadata name="traceViewItemBindingSource.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
121 <value>17, 17</value>
124 <value>17, 17</value>
122 </metadata>
125 </metadata>
123 </root> No newline at end of file
126 </root>
@@ -1,25 +1,26
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 using System.Threading.Tasks;
5 using System.Threading.Tasks;
6
6
7 namespace Implab.Diagnostics.Interactive {
7 namespace Implab.Diagnostics.Interactive {
8 public class TraceViewItem {
8 public class TraceViewItem {
9 string m_formattedValue;
9 string m_formattedValue;
10
10
11 public string Message { get; set; }
11 public string Message { get; set; }
12 public int Timestamp { get; set; }
12 public int Timestamp { get; set; }
13 public int Indent { get; set; }
13 public int Indent { get; set; }
14 public int Thread { get; set; }
14 public int Thread { get; set; }
15 public string Channel { get; set; }
15
16
16 public string FormattedMessage {
17 public string FormattedMessage {
17 get {
18 get {
18 if (m_formattedValue == null) {
19 if (m_formattedValue == null) {
19 m_formattedValue = Message.Replace("\r",String.Empty).Replace("\n", " | ");
20 m_formattedValue = Message.Replace("\r",String.Empty).Replace("\n", " | ");
20 }
21 }
21 return m_formattedValue;
22 return m_formattedValue;
22 }
23 }
23 }
24 }
24 }
25 }
25 }
26 }
@@ -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 local)
16 public ConsoleTraceListener(bool global)
17 : base(local) {
17 : base(global) {
18
18
19 }
19 }
20
20
21 protected override void WriteEntry(TraceContext context, EventText text) {
21 protected override void WriteEntry(TraceContext context, 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}", context.ThreadId, text.content);
26 msg.AppendFormat("[{0}]:{1}: {2}", context.ThreadId, channel, text.content);
27
27
28 lock (_consoleLock) {
28 lock (_consoleLock) {
29 Console.ForegroundColor = (ConsoleColor)(context.ThreadId % 15 + 1);
29 Console.ForegroundColor = (ConsoleColor)(context.ThreadId % 15 + 1);
30 Console.WriteLine(msg.ToString());
30 Console.WriteLine(msg.ToString());
31 }
31 }
32 }
32 }
33 }
33 }
34 }
34 }
@@ -1,30 +1,81
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>
8 /// Канал, Ρ‡Π΅Ρ€Π΅Π· ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΏΡƒΠ±Π»ΠΈΠΊΡƒΡŽΡ‚ΡΡ события ΠΆΡƒΡ€Π½Π°Π»Π°.
9 /// </summary>
10 /// <typeparam name="TEvent">Π’ΠΈΠΏ событий Π² ΠΊΠ°Π½Π°Π»Π΅</typeparam>
11 /// <remarks>
12 /// Бобытиями ΠΆΡƒΡ€Π½Π°Π»Π° ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ Π»ΡŽΠ±Ρ‹Π΅ Ρ‚ΠΈΠΏΡ‹, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ строки, Π² ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΠ΅Ρ€Π΅Π΄Π°Π²Π°Ρ‚ΡŒΡΡ
13 /// информация, ΠΈΠ»ΠΈ структуры с Π½Π°Π±ΠΎΡ€ΠΎΠΌ ΠΏΠΎΠ»Π΅ΠΉ, ΠΎΠΏΠΈΡΡ‹Π²Π°ΡŽΡ‰ΠΈΡ… Π²Π°ΠΆΠ½ΠΎΡΡ‚ΡŒ, тСкст ΠΈ Π΄Ρ€ΡƒΠ³ΡƒΡŽ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ.
14 /// </remarks>
7 public class LogChannel<TEvent> {
15 public class LogChannel<TEvent> {
8 static LogChannel<TEvent> _default = new LogChannel<TEvent>();
16 static LogChannel<TEvent> _default = new LogChannel<TEvent>();
9
17
18 /// <summary>
19 /// Канал ΠΏΠΎ-ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ для событий Ρ‚ΠΈΠΏΠ° <typeparam name="TEvent"/>.
20 /// </summary>
10 public static LogChannel<TEvent> Default {
21 public static LogChannel<TEvent> Default {
11 get {
22 get {
12 return _default;
23 return _default;
13 }
24 }
14 }
25 }
15
26
27 /// <summary>
28 /// Π‘ΠΎΠ±Ρ‹Ρ‚ΠΈΠ΅ появлСниС Π½ΠΎΠ²ΠΎΠΉ записи Π² ΠΆΡƒΡ€Π½Π°Π»Π΅, Π½Π° это событиС ΠΏΠΎΠ΄ΠΏΠΈΡΡ‹Π²Π°ΡŽΡ‚ΡΡ ΡΠ»ΡƒΡˆΠ°Ρ‚Π΅Π»ΠΈ.
29 /// </summary>
16 public event EventHandler<ValueEventArgs<TEvent>> Events;
30 public event EventHandler<ValueEventArgs<TEvent>> Events;
17
31
32 /// <summary>
33 /// Имя ΠΊΠ°Π½Π°Π»Π°, ΠΏΠΎΠ»Π΅Π·Π½ΠΎ для отобраТСния Π² ΠΆΡƒΡ€Π½Π°Π»Π΅
34 /// </summary>
35 public string Name {
36 get;
37 private set;
38 }
39
40 /// <summary>
41 /// Π‘ΠΎΠ·Π΄Π°Π΅Ρ‚ ΠΆΡƒΡ€Π½Π°Π», имя Ρ‚ΠΈΠΏΠ° событий назначаСтся Π² ΠΊΠ°Ρ‡Π΅Ρ‚Π²Π΅ ΠΈΠΌΠ΅Π½ΠΈ ΠΊΠ°Π½Π°Π»Π°.
42 /// </summary>
43 public LogChannel()
44 : this(null) {
45 }
46
47 /// <summary>
48 /// Π‘ΠΎΠ΄Π°Π΅Ρ‚ ΠΊΠ°Π½Π°Π» с ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹ΠΌ ΠΈΠΌΠ΅Π½Π΅ΠΌ.
49 /// </summary>
50 /// <param name="name">Имя канала.</param>
51 public LogChannel(string name) {
52 if (String.IsNullOrEmpty(name))
53 name = typeof(TEvent).Name;
54 Name = name;
55 }
56
57 /// <summary>
58 /// ΠžΡ‚ΠΏΡ€Π°Π²Π»ΡΠ΅Ρ‚ запись ΠΆΡƒΡ€Π½Π°Π»Π° Ρ‡Π΅Ρ€Π΅Π· ΠΊΠ°Π½Π°Π» подписчикам.
59 /// </summary>
60 /// <param name="data">Π—Π°ΠΏΠΈΡΡŒ ΠΆΡƒΡ€Π½Π°Π»Π°.</param>
61 /// <remarks>
62 /// ΠšΠΎΠ½Ρ‚Π΅ΠΊΡΡ‚ трассировки ΠΎΡ‚ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ рассылаСтся сообщСниС опрСдСляСтся автоматичСски ΠΈΠ· Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π³ΠΎ ΠΏΠΎΡ‚ΠΎΠΊΠ°.
63 /// </remarks>
18 public void LogEvent(TEvent data) {
64 public void LogEvent(TEvent data) {
19 var t = Events;
65 var t = Events;
20 if (t!= null)
66 if (t!= null)
21 t(TraceContext.Current,new ValueEventArgs<TEvent>(data));
67 t(TraceContext.Current,new ValueEventArgs<TEvent>(data));
22 }
68 }
23
69
70 /// <summary>
71 /// ΠžΡ‚ΠΏΡ€Π°Π²Π»ΡΠ΅Ρ‚ запись ΠΆΡƒΡ€Π½Π°Π»Π° Ρ‡Π΅Ρ€Π΅Π· ΠΊΠ°Π½Π°Π» подписчикам.
72 /// </summary>
73 /// <param name="data">Π—Π°ΠΏΠΈΡΡŒ ΠΆΡƒΡ€Π½Π°Π»Π°.</param>
74 /// <param name="context">ΠšΠΎΠ½Ρ‚Π΅ΠΊΡΡ‚ трассировки ΠΎΡ‚ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ рассылаСтся сообщСниС/</param>
24 public void LogEvent(TraceContext context,TEvent data) {
75 public void LogEvent(TraceContext context,TEvent data) {
25 var t = Events;
76 var t = Events;
26 if (t != null)
77 if (t != null)
27 t(context, new ValueEventArgs<TEvent>(data));
78 t(context, new ValueEventArgs<TEvent>(data));
28 }
79 }
29 }
80 }
30 }
81 }
@@ -1,46 +1,47
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.IO;
3 using System.IO;
4 using System.Linq;
4 using System.Linq;
5 using System.Text;
5 using System.Text;
6
6
7 namespace Implab.Diagnostics {
7 namespace Implab.Diagnostics {
8 public class TextFileListener: TextListenerBase {
8 public class TextFileListener: TextListenerBase {
9 readonly TextWriter m_textWriter;
9 readonly TextWriter m_textWriter;
10
10
11 public TextFileListener(string fileName, bool local) : base(local) {
11 public TextFileListener(string fileName, bool global)
12 : base(global) {
12 m_textWriter = File.CreateText(fileName);
13 m_textWriter = File.CreateText(fileName);
13
14
14 m_textWriter.WriteLine("LOG {0}", DateTime.Now);
15 m_textWriter.WriteLine("LOG {0}", DateTime.Now);
15 Register(this);
16 Register(this);
16 }
17 }
17
18
18 protected override void WriteEntry(TraceContext context, EventText text) {
19 protected override void WriteEntry(TraceContext context, EventText text, string channel) {
19 var msg = new StringBuilder();
20 var msg = new StringBuilder();
20 for (int i = 0; i < text.indent; i++)
21 for (int i = 0; i < text.indent; i++)
21 msg.Append(" ");
22 msg.Append(" ");
22 msg.AppendFormat("[{0}]: {1}", context.ThreadId, text.content);
23 msg.AppendFormat("[{0}]:{1}: {2}", context.ThreadId, channel, text.content);
23
24
24 lock (m_textWriter) {
25 lock (m_textWriter) {
25 if (!IsDisposed) {
26 if (!IsDisposed) {
26 // Ρ‚ΡƒΡ‚ Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½ΠΎ Π΅Ρ‰Π΅ Π½Π΅ освобоТдСн m_textWriter
27 // Ρ‚ΡƒΡ‚ Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½ΠΎ Π΅Ρ‰Π΅ Π½Π΅ освобоТдСн m_textWriter
27 m_textWriter.WriteLine(msg.ToString());
28 m_textWriter.WriteLine(msg.ToString());
28 m_textWriter.Flush();
29 m_textWriter.Flush();
29 }
30 }
30 }
31 }
31 }
32 }
32
33
33
34
34 protected override void Dispose(bool disposing) {
35 protected override void Dispose(bool disposing) {
35 base.Dispose(disposing);
36 base.Dispose(disposing);
36 if (disposing) {
37 if (disposing) {
37 // IsDisposed = true
38 // IsDisposed = true
38 lock (m_textWriter) {
39 lock (m_textWriter) {
39 Safe.Dispose(m_textWriter);
40 Safe.Dispose(m_textWriter);
40 }
41 }
41 }
42 }
42 }
43 }
43
44
44
45
45 }
46 }
46 }
47 }
@@ -1,128 +1,129
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 local) {
13 protected TextListenerBase(bool global) {
14 Register(this);
14 Register(this);
15 if (local) {
15 if (!global) {
16 m_boundOperation = TraceContext.Current.CurrentOperation;
16 m_boundOperation = TraceContext.Current.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
40
40 EventHandler<ValueEventArgs<TEvent>> handler = (sender, args) => {
41 EventHandler<ValueEventArgs<TEvent>> handler = (sender, args) => {
41 TraceContext context = (TraceContext)sender;
42 TraceContext context = (TraceContext)sender;
42 var text = formatter.Format(context, args.Value);
43 var text = formatter.Format(context, args.Value);
43 text.indent -= m_baseIndent;
44 text.indent -= m_baseIndent;
44
45
45 if (IsRelated(context.CurrentOperation))
46 if (IsRelated(context.CurrentOperation))
46 WriteEntry(context, text);
47 WriteEntry(context, text, channelName);
47 };
48 };
48
49
49 if (m_subscriptions.ContainsKey(channel))
50 if (m_subscriptions.ContainsKey(channel))
50 return;
51 return;
51
52
52 channel.Events += handler;
53 channel.Events += handler;
53
54
54 Action unsubscribe = () => {
55 Action unsubscribe = () => {
55 channel.Events -= handler;
56 channel.Events -= handler;
56 };
57 };
57
58
58 m_subscriptions.Add(channel, unsubscribe);
59 m_subscriptions.Add(channel, unsubscribe);
59 }
60 }
60 }
61 }
61
62
62 public bool IsRelated(LogicalOperation op) {
63 public bool IsRelated(LogicalOperation op) {
63 if (m_boundOperation == null)
64 if (m_boundOperation == null)
64 return true;
65 return true;
65
66
66 while (op != m_boundOperation && op.Level > m_boundOperation.Level)
67 while (op != m_boundOperation && op.Level > m_boundOperation.Level)
67 op = op.Parent;
68 op = op.Parent;
68 return op == m_boundOperation;
69 return op == m_boundOperation;
69 }
70 }
70
71
71 public void Unsubscribe<TEvent>(LogChannel<TEvent> channel) {
72 public void Unsubscribe<TEvent>(LogChannel<TEvent> channel) {
72 if (channel == null)
73 if (channel == null)
73 throw new ArgumentNullException("channel");
74 throw new ArgumentNullException("channel");
74
75
75 lock (m_subscriptions) {
76 lock (m_subscriptions) {
76 Action subscription;
77 Action subscription;
77 if (m_subscriptions.TryGetValue(channel, out subscription)) {
78 if (m_subscriptions.TryGetValue(channel, out subscription)) {
78 subscription();
79 subscription();
79 m_subscriptions.Remove(channel);
80 m_subscriptions.Remove(channel);
80 }
81 }
81 }
82 }
82 }
83 }
83
84
84 public void UnsubscribeAll() {
85 public void UnsubscribeAll() {
85 lock (m_subscriptions) {
86 lock (m_subscriptions) {
86 foreach (var subscription in m_subscriptions.Values)
87 foreach (var subscription in m_subscriptions.Values)
87 subscription();
88 subscription();
88 m_subscriptions.Clear();
89 m_subscriptions.Clear();
89 }
90 }
90 }
91 }
91
92
92 /// <summary>
93 /// <summary>
93 /// ВызываСтся для записи тСкста сообщСния, Π² ΠΆΡƒΡ€Π½Π°Π».
94 /// ВызываСтся для записи тСкста сообщСния, Π² ΠΆΡƒΡ€Π½Π°Π».
94 /// </summary>
95 /// </summary>
95 /// <remarks>
96 /// <remarks>
96 /// Π”Π°Π½Π½Ρ‹ΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ ΠΌΠΎΠΆΠ΅Ρ‚ Π²Ρ‹Π·Π²Π°Ρ‚ΡŒΡΡ ΠΈΠ· Ρ€Π°Π·Π½Ρ‹Ρ… ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ. Π’ΠΎΠ·ΠΌΠΎΠΆΠ½Π° ситуация, ΠΊΠΎΠ³Π΄Π°
97 /// Π”Π°Π½Π½Ρ‹ΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ ΠΌΠΎΠΆΠ΅Ρ‚ Π²Ρ‹Π·Π²Π°Ρ‚ΡŒΡΡ ΠΈΠ· Ρ€Π°Π·Π½Ρ‹Ρ… ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ. Π’ΠΎΠ·ΠΌΠΎΠΆΠ½Π° ситуация, ΠΊΠΎΠ³Π΄Π°
97 /// Π΄Π°Π½Π½Ρ‹ΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ вызываСтся ΡƒΠΆΠ΅ послС освобоТдСния ΠΎΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠΌ <see cref="Dispose()"/>.
98 /// Π΄Π°Π½Π½Ρ‹ΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ вызываСтся ΡƒΠΆΠ΅ послС освобоТдСния ΠΎΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠΌ <see cref="Dispose()"/>.
98 /// </remarks>
99 /// </remarks>
99 /// <param name="context">ΠšΠΎΠ½Ρ‚Π΅ΠΊΡΡ‚ трассировки.</param>
100 /// <param name="context">ΠšΠΎΠ½Ρ‚Π΅ΠΊΡΡ‚ трассировки.</param>
100 /// <param name="text">ВСкст сообщСния.</param>
101 /// <param name="text">ВСкст сообщСния.</param>
101 protected abstract void WriteEntry(TraceContext context, EventText text);
102 protected abstract void WriteEntry(TraceContext context, EventText text, string channel);
102
103
103 public EventText Format(TraceContext context, object data) {
104 public EventText Format(TraceContext context, object data) {
104 return new EventText {
105 return new EventText {
105 indent = context.CurrentOperation.Level,
106 indent = context.CurrentOperation.Level,
106 content = data.ToString()
107 content = data.ToString()
107 };
108 };
108 }
109 }
109
110
110 public EventText Format(TraceContext context, TraceEvent data) {
111 public EventText Format(TraceContext context, TraceEvent data) {
111 var level = context.CurrentOperation.Level;
112 var level = context.CurrentOperation.Level;
112 if (data.EventType == TraceEventType.OperationCompleted || data.EventType == TraceEventType.OperationStarted)
113 if (data.EventType == TraceEventType.OperationCompleted || data.EventType == TraceEventType.OperationStarted)
113 level--;
114 level--;
114
115
115 return new EventText {
116 return new EventText {
116 indent = level,
117 indent = level,
117 content = data.ToString()
118 content = data.ToString()
118 };
119 };
119 }
120 }
120
121
121 protected override void Dispose(bool disposing) {
122 protected override void Dispose(bool disposing) {
122 base.Dispose(disposing);
123 base.Dispose(disposing);
123 if (disposing) {
124 if (disposing) {
124 UnsubscribeAll();
125 UnsubscribeAll();
125 }
126 }
126 }
127 }
127 }
128 }
128 }
129 }
@@ -1,172 +1,211
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 using System.Threading;
5 using System.Threading;
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 /// ΠšΠΎΠ½Ρ‚Π΅ΠΊΡΡ‚ трассировки, привязываСтся ΠΊ ΠΏΠΎΡ‚ΠΎΠΊΡƒ ΠΈ содСрТит Π² сСбС ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎ стСкС логичСских ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ.
10 /// ΠšΠΎΠ½Ρ‚Π΅ΠΊΡΡ‚ трассировки, привязываСтся ΠΊ ΠΏΠΎΡ‚ΠΎΠΊΡƒ ΠΈ содСрТит Π² сСбС ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎ стСкС логичСских ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ.
11 /// </summary>
11 /// </summary>
12 /// <remarks>
12 /// <remarks>
13 /// ΠšΠΎΠ½Ρ‚Π΅ΠΊΡΡ‚ трассировки пСрСдаСтся ΡΠ»ΡƒΡˆΠ°Ρ‚Π΅Π»ΡΠΌ событий для опрСдСлСния мСста, Π³Π΄Π΅ Π²ΠΎΠ·Π½ΠΈΠΊΠ»ΠΎ событиС.
13 /// ΠšΠΎΠ½Ρ‚Π΅ΠΊΡΡ‚ трассировки пСрСдаСтся ΡΠ»ΡƒΡˆΠ°Ρ‚Π΅Π»ΡΠΌ событий для опрСдСлСния мСста, Π³Π΄Π΅ Π²ΠΎΠ·Π½ΠΈΠΊΠ»ΠΎ событиС.
14 /// </remarks>
14 /// </remarks>
15 public class TraceContext {
15 public class TraceContext {
16 LogicalOperation m_currentOperation;
16 LogicalOperation m_currentOperation;
17 readonly LogicalOperation m_bound;
17 readonly LogicalOperation m_bound;
18 readonly int m_threadId;
18 readonly int m_threadId;
19
19
20 [ThreadStatic]
20 [ThreadStatic]
21 static TraceContext _current;
21 static TraceContext _current;
22
22
23 /// <summary>
23 /// <summary>
24 /// Π’Π΅ΠΊΡƒΡ‰ΠΈΠΉ контСкст трассировки для ΠΏΠΎΡ‚ΠΎΠΊΠ°, создаСтся астоматичСски ΠΏΡ€ΠΈ ΠΏΠ΅Ρ€Π²ΠΎΠΌ ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠΈ.
24 /// Π’Π΅ΠΊΡƒΡ‰ΠΈΠΉ контСкст трассировки для ΠΏΠΎΡ‚ΠΎΠΊΠ°, создаСтся астоматичСски ΠΏΡ€ΠΈ ΠΏΠ΅Ρ€Π²ΠΎΠΌ ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠΈ.
25 /// </summary>
25 /// </summary>
26 public static TraceContext Current {
26 public static TraceContext Current {
27 get {
27 get {
28 if (_current == null)
28 if (_current == null) {
29 _current = new TraceContext();
29 _current = new TraceContext();
30 _current.LogEvent(TraceEventType.Created,"[{0}]", _current.ThreadId);
31 }
30 return _current;
32 return _current;
31 }
33 }
32 }
34 }
33
35
34 TraceContext(TraceContext context) {
36 TraceContext(TraceContext context)
37 : this(context, false) {
38 }
39
40 TraceContext(TraceContext context, bool attach) {
35 if (context == null)
41 if (context == null)
36 throw new ArgumentNullException("context");
42 throw new ArgumentNullException("context");
37
43
38 m_currentOperation = context.CurrentOperation;
44 m_currentOperation = context.CurrentOperation;
39 m_bound = context.CurrentOperation;
45 m_bound = attach ? context.BoundOperation : context.CurrentOperation;
40 m_threadId = Thread.CurrentThread.ManagedThreadId;
46 m_threadId = Thread.CurrentThread.ManagedThreadId;
41 }
47 }
42
48
43 TraceContext() {
49 TraceContext() {
44 m_currentOperation = new LogicalOperation();
50 m_currentOperation = new LogicalOperation();
45 m_bound = m_currentOperation;
51 m_bound = m_currentOperation;
46 m_threadId = Thread.CurrentThread.ManagedThreadId;
52 m_threadId = Thread.CurrentThread.ManagedThreadId;
47 }
53 }
48
54
49 /// <summary>
55 /// <summary>
50 /// ΠŸΡ€ΠΈ нСобходимости ΠΊΠΎΠΏΠΈΡ€ΡƒΠ΅Ρ‚ состояниС контСкста трассивровки Π² Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΉ ΠΏΠΎΡ‚ΠΎΠΊ.
56 /// ΠŸΡ€ΠΈ нСобходимости ΠΊΠΎΠΏΠΈΡ€ΡƒΠ΅Ρ‚ состояниС контСкста трассивровки Π² Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΉ ΠΏΠΎΡ‚ΠΎΠΊ.
51 /// </summary>
57 /// </summary>
52 /// <param name="from">Π˜ΡΡ…ΠΎΠ΄Π½Ρ‹ΠΉ контСкст трассировки, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ пСрСдаСтся.</param>
58 /// <param name="from">Π˜ΡΡ…ΠΎΠ΄Π½Ρ‹ΠΉ контСкст трассировки, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ пСрСдаСтся.</param>
53 /// <remarks>
59 /// <remarks>
54 /// <para>
60 /// <para>
55 /// ΠšΠΎΠΏΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ происходит Π·Π° счСт создания Π½ΠΎΠ²ΠΎΠ³ΠΎ контСкста трассировки ΠΈ Π·Π°ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ΠΌ Π΅Π³ΠΎ
61 /// ΠšΠΎΠΏΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ происходит Π·Π° счСт создания Π½ΠΎΠ²ΠΎΠ³ΠΎ контСкста трассировки ΠΈ Π·Π°ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ΠΌ Π΅Π³ΠΎ
56 /// состояния ΠΈΠ· ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½ΠΎΠ³ΠΎ контСкста. ΠŸΡ€ΠΈ этом копируСтся стСк ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ, ΠΎΠ΄Π½Π°ΠΊΠΎ Π² Π½ΠΎΠ²ΠΎΠΌ
62 /// состояния ΠΈΠ· ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½ΠΎΠ³ΠΎ контСкста. ΠŸΡ€ΠΈ этом копируСтся стСк ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ, ΠΎΠ΄Π½Π°ΠΊΠΎ Π² Π½ΠΎΠ²ΠΎΠΌ
57 /// контСкстС Ρ€Π°Π½Π΅Π΅ Π½Π°Ρ‡Π°Ρ‚Ρ‹Π΅ логичСскиС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ Π½Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½Ρ‹.
63 /// контСкстС Ρ€Π°Π½Π΅Π΅ Π½Π°Ρ‡Π°Ρ‚Ρ‹Π΅ логичСскиС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ Π½Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½Ρ‹.
58 /// </para>
64 /// </para>
59 /// <para>
65 /// <para>
60 /// Если ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Π° состояния ΡΠΎΡΡ‚ΠΎΡΠ»Π°ΡΡŒ, Ρ‚ΠΎ вызываСтся событиС трассировки <see cref="TraceEventType.Transfer"/>.
66 /// Если ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Π° состояния ΡΠΎΡΡ‚ΠΎΡΠ»Π°ΡΡŒ, Ρ‚ΠΎ вызываСтся событиС трассировки <see cref="TraceEventType.Fork"/>.
61 /// </para>
67 /// </para>
62 /// </remarks>
68 /// </remarks>
63 public static void Transfer(TraceContext from) {
69 public static void Fork(TraceContext from) {
64 if (_current == from)
70 if (_current == from)
65 return;
71 return;
66 if (from != null) {
72 if (from != null) {
67 var context = new TraceContext(from);
73 var context = new TraceContext(from);
68 context.LogEvent(TraceEventType.Transfer, "[{0}]-->[{1}]",from.ThreadId, context.ThreadId);
74 context.LogEvent(TraceEventType.Fork, "[{0}]-->[{1}]",from.ThreadId, context.ThreadId);
69 _current = context;
75 _current = context;
70 } else {
76 } else {
71 _current = new TraceContext();
77 _current = new TraceContext();
72 }
78 }
73 }
79 }
74
80
75 /// <summary>
81 /// <summary>
76 /// Π‘ΠΎΠ·Π΄Π°Π΅Ρ‚ ΠΏΠΎΡΡ‚ΠΎΡΠ½Π½ΡƒΡŽ копию Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π³ΠΎ контСкста, Π΄Π°Π½Π½ΡƒΡŽ копию ΠΌΠΎΠΆΠ½ΠΎ Ρ…Ρ€Π°Π½ΠΈΡ‚ΡŒ ΠΈ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ для ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ Ρ‡Π΅Ρ€Π΅Π· <see cref="Transfer(TraceContext)"/>
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)"/>
77 /// </summary>
116 /// </summary>
78 /// <returns>Копия Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π³ΠΎ контСкста трассировки.</returns>
117 /// <returns>Копия Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π³ΠΎ контСкста трассировки.</returns>
79 public static TraceContext Snapshot() {
118 public static TraceContext Snapshot() {
80 return _current == null ? new TraceContext() : new TraceContext(_current);
119 return _current == null ? new TraceContext() : new TraceContext(_current);
81 }
120 }
82
121
83 /// <summary>
122 /// <summary>
84 /// ВыполняСт ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½ΠΎΠ΅ дСйствиС Π² ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΌ контСкстС трассировки, ΠΏΠΎ ΠΎΠΊΠΎΠ½Ρ‡Π°Π½ΠΈΠΈ восстанавливаСт ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΠΈΠΉ контСкст трассировки ΠΏΠΎΡ‚ΠΎΠΊΠ°.
123 /// ВыполняСт ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½ΠΎΠ΅ дСйствиС Π² ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΌ контСкстС трассировки, ΠΏΠΎ ΠΎΠΊΠΎΠ½Ρ‡Π°Π½ΠΈΠΈ восстанавливаСт ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΠΈΠΉ контСкст трассировки ΠΏΠΎΡ‚ΠΎΠΊΠ°.
85 /// </summary>
124 /// </summary>
86 /// <param name="action"></param>
125 /// <param name="action"></param>
87 public void Invoke(Action action) {
126 public void Invoke(Action action) {
88 if (action == null)
127 if (action == null)
89 throw new ArgumentNullException("action");
128 throw new ArgumentNullException("action");
90 var old = _current;
129 var old = _current;
91 Transfer(this);
130 Fork(this);
92 try {
131 try {
93 action();
132 action();
94 } finally {
133 } finally {
95 _current.EndAllOperations();
134 _current.EndAllOperations();
96 _current = old;
135 _current = old;
97 }
136 }
98 }
137 }
99
138
100 /// <summary>
139 /// <summary>
101 /// ВСкущая логичСская опСрация.
140 /// ВСкущая логичСская опСрация.
102 /// </summary>
141 /// </summary>
103 public LogicalOperation CurrentOperation {
142 public LogicalOperation CurrentOperation {
104 get {
143 get {
105 return m_currentOperation;
144 return m_currentOperation;
106 }
145 }
107 }
146 }
108
147
109 /// <summary>
148 /// <summary>
110 /// ΠžΠΏΠ΅Ρ€Π°Ρ†ΠΈΡ Π½ΠΈΠΆΠ΅ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ нСльзя ΠΎΠΏΡƒΡΠΊΠ°Ρ‚ΡŒΡΡ Π² стСкС логичСских ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ, Ρ‚.Π΅. ΠΎΠ½Π° Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½Π° Π² Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌ контСкстС.
149 /// ΠžΠΏΠ΅Ρ€Π°Ρ†ΠΈΡ Π½ΠΈΠΆΠ΅ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ нСльзя ΠΎΠΏΡƒΡΠΊΠ°Ρ‚ΡŒΡΡ Π² стСкС логичСских ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ, Ρ‚.Π΅. ΠΎΠ½Π° Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½Π° Π² Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌ контСкстС.
111 /// </summary>
150 /// </summary>
112 public LogicalOperation BoundOperation {
151 public LogicalOperation BoundOperation {
113 get {
152 get {
114 return m_bound;
153 return m_bound;
115 }
154 }
116 }
155 }
117
156
118 /// <summary>
157 /// <summary>
119 /// ΠŸΠΎΡ‚ΠΎΠΊ, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ создан контСкст трассировки.
158 /// ΠŸΠΎΡ‚ΠΎΠΊ, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ создан контСкст трассировки.
120 /// </summary>
159 /// </summary>
121 public int ThreadId {
160 public int ThreadId {
122 get {
161 get {
123 return m_threadId;
162 return m_threadId;
124 }
163 }
125 }
164 }
126
165
127 /// <summary>
166 /// <summary>
128 /// НачинаСт Π±Π΅Π·Ρ‹ΠΌΡΠ½Π½ΡƒΡŽ Π»ΠΎΠ³ΠΈΡ‡Π΅ΡΠΊΡƒΡŽ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ.
167 /// НачинаСт Π±Π΅Π·Ρ‹ΠΌΡΠ½Π½ΡƒΡŽ Π»ΠΎΠ³ΠΈΡ‡Π΅ΡΠΊΡƒΡŽ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ.
129 /// </summary>
168 /// </summary>
130 public void StartLogicalOperation() {
169 public void StartLogicalOperation() {
131 StartLogicalOperation(null);
170 StartLogicalOperation(null);
132 }
171 }
133
172
134 /// <summary>
173 /// <summary>
135 /// НачинаСт Π»ΠΎΠ³ΠΈΡ‡Π΅ΡΠΊΡƒΡŽ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ с ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹ΠΌ ΠΈΠΌΠ΅Π½Π΅ΠΌ. Бозданная опСрация Π±ΡƒΠ΄Π΅Ρ‚ Π΄ΠΎΠ±Π²Π°Π»Π΅Π½Π° Π² стСк логичСских ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ контСкста, Π·Π°Ρ‚Π΅ΠΌ Π±ΡƒΠ΄Π΅Ρ‚ создано ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΠ²ΡƒΡŽΡ‰Π΅Π΅ событиС.
174 /// НачинаСт Π»ΠΎΠ³ΠΈΡ‡Π΅ΡΠΊΡƒΡŽ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ с ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹ΠΌ ΠΈΠΌΠ΅Π½Π΅ΠΌ. Бозданная опСрация Π±ΡƒΠ΄Π΅Ρ‚ Π΄ΠΎΠ±Π²Π°Π»Π΅Π½Π° Π² стСк логичСских ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ контСкста, Π·Π°Ρ‚Π΅ΠΌ Π±ΡƒΠ΄Π΅Ρ‚ создано ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΠ²ΡƒΡŽΡ‰Π΅Π΅ событиС.
136 /// </summary>
175 /// </summary>
137 /// <param name="name">Имя Π½Π°Ρ‡ΠΈΠ½Π°Π΅ΠΌΠΎΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</param>
176 /// <param name="name">Имя Π½Π°Ρ‡ΠΈΠ½Π°Π΅ΠΌΠΎΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</param>
138 public void StartLogicalOperation(string name) {
177 public void StartLogicalOperation(string name) {
139 m_currentOperation = new LogicalOperation(name, m_currentOperation);
178 m_currentOperation = new LogicalOperation(name, m_currentOperation);
140 LogEvent(TraceEventType.OperationStarted, name);
179 LogEvent(TraceEventType.OperationStarted, name);
141 }
180 }
142
181
143 /// <summary>
182 /// <summary>
144 /// Π—Π°ΠΊΠ°Π½Ρ‡ΠΈΠ²Π°Π΅Ρ‚ Π»ΠΎΠ³ΠΈΡ‡Π΅ΡΠΊΡƒΡŽ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ Π½Π°Ρ‡Π°Ρ‚ΡƒΡŽ Π² Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌ контСкстС. ΠžΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, Π½Π°Ρ‡Π°Ρ‚Ρ‹Π΅ Π² Π΄Ρ€ΡƒΠ³ΠΈΡ… контСкстах Π½Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ Π·Π°ΠΊΠΎΠ½Ρ‡Π΅Π½Ρ‹ Π² Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌ контСкстС.
183 /// Π—Π°ΠΊΠ°Π½Ρ‡ΠΈΠ²Π°Π΅Ρ‚ Π»ΠΎΠ³ΠΈΡ‡Π΅ΡΠΊΡƒΡŽ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ Π½Π°Ρ‡Π°Ρ‚ΡƒΡŽ Π² Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌ контСкстС. ΠžΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, Π½Π°Ρ‡Π°Ρ‚Ρ‹Π΅ Π² Π΄Ρ€ΡƒΠ³ΠΈΡ… контСкстах Π½Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ Π·Π°ΠΊΠΎΠ½Ρ‡Π΅Π½Ρ‹ Π² Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌ контСкстС.
145 /// </summary>
184 /// </summary>
146 /// <remarks>
185 /// <remarks>
147 /// ΠŸΡ€ΠΈ Π²Ρ‹Π·ΠΎΠ²Π΅ Π΄Π°Π½Π½ΠΎΠ³ΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄Π° создаСтся событиС ΠΆΡƒΡ€Π½Π°Π»Π° трассировки, Π»ΠΈΠ±ΠΎ ΠΎ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, Π»ΠΈΠ±ΠΎ ΠΎΠ± ошибки, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ данная опСрация
186 /// ΠŸΡ€ΠΈ Π²Ρ‹Π·ΠΎΠ²Π΅ Π΄Π°Π½Π½ΠΎΠ³ΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄Π° создаСтся событиС ΠΆΡƒΡ€Π½Π°Π»Π° трассировки, Π»ΠΈΠ±ΠΎ ΠΎ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, Π»ΠΈΠ±ΠΎ ΠΎΠ± ошибки, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ данная опСрация
148 /// Π½Π°Ρ‡Π°Ρ‚Π° Π² Π΄Ρ€ΡƒΠ³ΠΎΠΌ контСкстС.
187 /// Π½Π°Ρ‡Π°Ρ‚Π° Π² Π΄Ρ€ΡƒΠ³ΠΎΠΌ контСкстС.
149 /// </remarks>
188 /// </remarks>
150 public void EndLogicalOperation() {
189 public void EndLogicalOperation() {
151 if (m_bound == m_currentOperation) {
190 if (m_bound == m_currentOperation) {
152 LogEvent(TraceEventType.Error, "Trying to end the operation which isn't belongs to current trace");
191 LogEvent(TraceEventType.Error, "Trying to end the operation which isn't belongs to current trace");
153 } else {
192 } else {
154 var op = m_currentOperation;
193 var op = m_currentOperation;
155 LogEvent(TraceEventType.OperationCompleted, "{0} {1} ms", op.Name, op.Duration);
194 LogEvent(TraceEventType.OperationCompleted, "{0} {1} ms", op.Name, op.Duration);
156 m_currentOperation = m_currentOperation.Parent;
195 m_currentOperation = m_currentOperation.Parent;
157 }
196 }
158 }
197 }
159
198
160 /// <summary>
199 /// <summary>
161 /// Π—Π°Π²Ρ€Π΅ΡˆΠ°Π΅Ρ‚ всС Π½Π°Ρ‡Π°Ρ‚Ρ‹Π΅ Π² этом контСкстС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ
200 /// Π—Π°Π²Ρ€Π΅ΡˆΠ°Π΅Ρ‚ всС Π½Π°Ρ‡Π°Ρ‚Ρ‹Π΅ Π² этом контСкстС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ
162 /// </summary>
201 /// </summary>
163 public void EndAllOperations() {
202 public void EndAllOperations() {
164 while (m_bound != m_currentOperation)
203 while (m_bound != m_currentOperation)
165 EndLogicalOperation();
204 EndLogicalOperation();
166 }
205 }
167
206
168 void LogEvent(TraceEventType type, string format, params object[] args) {
207 void LogEvent(TraceEventType type, string format, params object[] args) {
169 LogChannel<TraceEvent>.Default.LogEvent(this, TraceEvent.Create(type, format, args));
208 LogChannel<TraceEvent>.Default.LogEvent(this, TraceEvent.Create(type, format, args));
170 }
209 }
171 }
210 }
172 }
211 }
@@ -1,16 +1,19
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 using System.Threading.Tasks;
5 using System.Threading.Tasks;
6
6
7 namespace Implab.Diagnostics {
7 namespace Implab.Diagnostics {
8 public enum TraceEventType {
8 public enum TraceEventType {
9 Information = 1,
9 Information = 1,
10 Warning,
10 Warning,
11 Error,
11 Error,
12 OperationStarted,
12 OperationStarted,
13 OperationCompleted,
13 OperationCompleted,
14 Transfer
14 Fork,
15 Attach,
16 Detach,
17 Created
15 }
18 }
16 }
19 }
@@ -1,46 +1,62
1 using System;
1 using Implab.Diagnostics;
2 using System;
2 using System.Collections.Generic;
3 using System.Collections.Generic;
3 using System.Diagnostics;
4 using System.Diagnostics;
4 using System.Linq;
5 using System.Linq;
5 using System.Web;
6 using System.Web;
6
7
7 namespace Implab {
8 namespace Implab {
9 /// <summary>
10 /// ΠžΠ±ΡŠΠ΅ΠΊΡ‚, ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°ΡŽΡ‰ΠΈΠΉ освобоТдСниС рСсурсов.
11 /// </summary>
8 public class Disposable : IDisposable {
12 public class Disposable : IDisposable {
9
13
10 bool m_disposed;
14 bool m_disposed;
11
15
12 public event EventHandler Disposed;
16 public event EventHandler Disposed;
13
17
14 public bool IsDisposed {
18 public bool IsDisposed {
15 get { return m_disposed; }
19 get { return m_disposed; }
16 }
20 }
17
21
18 protected void AssertNotDisposed() {
22 protected void AssertNotDisposed() {
19 if (m_disposed)
23 if (m_disposed)
20 throw new ObjectDisposedException(this.ToString());
24 throw new ObjectDisposedException(this.ToString());
21 }
25 }
22
26 /// <summary>
27 /// ΠŸΠ΅Ρ€Π΅Π²ΠΎΠ΄ΠΈΡ‚ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ Π² состояниС <c>Disposed</c> ΠΈ Π²Ρ‹Π·Ρ‹Π²Π°Π΅Ρ‚ событиС <see cref="Disposed"/>
28 /// </summary>
29 /// <param name="disposing">ΠŸΡ€ΠΈΠ·Π½Π°ΠΊ Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎ Π½ΡƒΠΆΠ½ΠΎ ΠΎΡΠ²ΠΎΠ±ΠΎΠ΄ΠΈΡ‚ΡŒ рСсурсы, ΠΈΠ½Π°Ρ‡Π΅ Π΄Π°Π½Π½Ρ‹ΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄
30 /// Π²Ρ‹Π·Π²Π°Π½ сборщиком мусора ΠΈ Π½ΡƒΠΆΠ½ΠΎ ΠΎΡΠ²ΠΎΠ±ΠΎΠΆΠ΄Π°Ρ‚ΡŒ Π’ΠžΠ›Π¬ΠšΠž нСуправляСмыС рСсурсы Π’ΠžΠ›Π¬ΠšΠž этого
31 /// ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°.</param>
32 /// <remarks>
33 /// Π”Π°Π½Π½Ρ‹ΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ осущСствляСт ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΡƒ Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ ΡƒΠΆΠ΅ Π±Ρ‹Π» освобоТдСн, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π½Π΅ Π²Ρ‹Π·Ρ‹Π²Π°Ρ‚ΡŒ
34 /// событиС <see cref="Disposed"/>. НС ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ ΠΌΠ½ΠΎΠ³ΠΎΠΏΠΎΡ‚ΠΎΡ‡Π½ΠΎΡΡ‚ΡŒ.
35 /// </remarks>
23 protected virtual void Dispose(bool disposing) {
36 protected virtual void Dispose(bool disposing) {
24 if (disposing && !m_disposed) {
37 if (disposing && !m_disposed) {
25 m_disposed = true;
38 m_disposed = true;
26
39
27 EventHandler temp = Disposed;
40 EventHandler temp = Disposed;
28 if (temp != null)
41 if (temp != null)
29 temp(this,EventArgs.Empty);
42 temp(this,EventArgs.Empty);
30 }
43 }
31 }
44 }
32 public void Dispose() {
45 public void Dispose() {
33 Dispose(true);
46 Dispose(true);
34 GC.SuppressFinalize(this);
47 GC.SuppressFinalize(this);
35 }
48 }
36
49
50 /// <summary>
51 /// ЗаписываСт сообщСниС ΠΎΠ± ΡƒΡ‚Π΅Ρ‡ΠΊΠ΅ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°.
52 /// </summary>
37 protected virtual void ReportObjectLeaks() {
53 protected virtual void ReportObjectLeaks() {
38 Trace.TraceWarning("The object is marked as disposable but isn't disposed properly: {0}", this);
54 TraceLog.TraceWarning("The object is marked as disposable but isn't disposed properly: {0}", this);
39 }
55 }
40
56
41 ~Disposable() {
57 ~Disposable() {
42 Dispose(false);
58 Dispose(false);
43 ReportObjectLeaks();
59 ReportObjectLeaks();
44 }
60 }
45 }
61 }
46 } No newline at end of file
62 }
@@ -1,191 +1,191
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 TraceContext m_traceContext;
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_traceContext = TraceContext.Snapshot();
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 m_promise.Cancelled(() => Dispose());
33 m_promise.Cancelled(() => Dispose());
34
34
35 InitPool();
35 InitPool();
36 }
36 }
37
37
38 public Promise<int> Promise {
38 public Promise<int> Promise {
39 get {
39 get {
40 return m_promise;
40 return m_promise;
41 }
41 }
42 }
42 }
43
43
44 protected override void Worker() {
44 protected override void Worker() {
45 TraceContext.Transfer(m_traceContext);
45 TraceContext.Fork(m_traceContext);
46 base.Worker();
46 base.Worker();
47 }
47 }
48
48
49 protected override bool TryDequeue(out int unit) {
49 protected override bool TryDequeue(out int unit) {
50 unit = Interlocked.Increment(ref m_next) - 1;
50 unit = Interlocked.Increment(ref m_next) - 1;
51 return unit >= m_source.Length ? false : true;
51 return unit >= m_source.Length ? false : true;
52 }
52 }
53
53
54 protected override void InvokeUnit(int unit) {
54 protected override void InvokeUnit(int unit) {
55 try {
55 try {
56 m_action(m_source[unit]);
56 m_action(m_source[unit]);
57 var pending = Interlocked.Decrement(ref m_pending);
57 var pending = Interlocked.Decrement(ref m_pending);
58 if (pending == 0)
58 if (pending == 0)
59 m_promise.Resolve(m_source.Length);
59 m_promise.Resolve(m_source.Length);
60 } catch (Exception e) {
60 } catch (Exception e) {
61 m_promise.Reject(e);
61 m_promise.Reject(e);
62 }
62 }
63 }
63 }
64 }
64 }
65
65
66 class ArrayMapper<TSrc, TDst>: DispatchPool<int> {
66 class ArrayMapper<TSrc, TDst>: DispatchPool<int> {
67 readonly Func<TSrc, TDst> m_transform;
67 readonly Func<TSrc, TDst> m_transform;
68 readonly TSrc[] m_source;
68 readonly TSrc[] m_source;
69 readonly TDst[] m_dest;
69 readonly TDst[] m_dest;
70 readonly Promise<TDst[]> m_promise = new Promise<TDst[]>();
70 readonly Promise<TDst[]> m_promise = new Promise<TDst[]>();
71 readonly TraceContext m_traceContext;
71 readonly TraceContext m_traceContext;
72
72
73 int m_pending;
73 int m_pending;
74 int m_next;
74 int m_next;
75
75
76 public ArrayMapper(TSrc[] source, Func<TSrc, TDst> transform, int threads)
76 public ArrayMapper(TSrc[] source, Func<TSrc, TDst> transform, int threads)
77 : base(threads) {
77 : base(threads) {
78
78
79 Debug.Assert (source != null);
79 Debug.Assert (source != null);
80 Debug.Assert( transform != null);
80 Debug.Assert( transform != null);
81
81
82 m_next = 0;
82 m_next = 0;
83 m_source = source;
83 m_source = source;
84 m_dest = new TDst[source.Length];
84 m_dest = new TDst[source.Length];
85 m_pending = source.Length;
85 m_pending = source.Length;
86 m_transform = transform;
86 m_transform = transform;
87 m_traceContext = TraceContext.Snapshot();
87 m_traceContext = TraceContext.Snapshot();
88
88
89 m_promise.Anyway(() => Dispose());
89 m_promise.Anyway(() => Dispose());
90 m_promise.Cancelled(() => Dispose());
90 m_promise.Cancelled(() => Dispose());
91
91
92 InitPool();
92 InitPool();
93 }
93 }
94
94
95 public Promise<TDst[]> Promise {
95 public Promise<TDst[]> Promise {
96 get {
96 get {
97 return m_promise;
97 return m_promise;
98 }
98 }
99 }
99 }
100
100
101 protected override void Worker() {
101 protected override void Worker() {
102 TraceContext.Transfer(m_traceContext);
102 TraceContext.Fork(m_traceContext);
103 base.Worker();
103 base.Worker();
104 }
104 }
105
105
106 protected override bool TryDequeue(out int unit) {
106 protected override bool TryDequeue(out int unit) {
107 unit = Interlocked.Increment(ref m_next) - 1;
107 unit = Interlocked.Increment(ref m_next) - 1;
108 return unit >= m_source.Length ? false : true;
108 return unit >= m_source.Length ? false : true;
109 }
109 }
110
110
111 protected override void InvokeUnit(int unit) {
111 protected override void InvokeUnit(int unit) {
112 try {
112 try {
113 m_dest[unit] = m_transform(m_source[unit]);
113 m_dest[unit] = m_transform(m_source[unit]);
114 var pending = Interlocked.Decrement(ref m_pending);
114 var pending = Interlocked.Decrement(ref m_pending);
115 if (pending == 0)
115 if (pending == 0)
116 m_promise.Resolve(m_dest);
116 m_promise.Resolve(m_dest);
117 } catch (Exception e) {
117 } catch (Exception e) {
118 m_promise.Reject(e);
118 m_promise.Reject(e);
119 }
119 }
120 }
120 }
121 }
121 }
122
122
123 public static IPromise<TDst[]> ParallelMap<TSrc, TDst> (this TSrc[] source, Func<TSrc,TDst> transform, int threads) {
123 public static IPromise<TDst[]> ParallelMap<TSrc, TDst> (this TSrc[] source, Func<TSrc,TDst> transform, int threads) {
124 if (source == null)
124 if (source == null)
125 throw new ArgumentNullException("source");
125 throw new ArgumentNullException("source");
126 if (transform == null)
126 if (transform == null)
127 throw new ArgumentNullException("transform");
127 throw new ArgumentNullException("transform");
128
128
129 var mapper = new ArrayMapper<TSrc, TDst>(source, transform, threads);
129 var mapper = new ArrayMapper<TSrc, TDst>(source, transform, threads);
130 return mapper.Promise;
130 return mapper.Promise;
131 }
131 }
132
132
133 public static IPromise<int> ParallelForEach<TSrc>(this TSrc[] source, Action<TSrc> action, int threads) {
133 public static IPromise<int> ParallelForEach<TSrc>(this TSrc[] source, Action<TSrc> action, int threads) {
134 if (source == null)
134 if (source == null)
135 throw new ArgumentNullException("source");
135 throw new ArgumentNullException("source");
136 if (action == null)
136 if (action == null)
137 throw new ArgumentNullException("action");
137 throw new ArgumentNullException("action");
138
138
139 var iter = new ArrayIterator<TSrc>(source, action, threads);
139 var iter = new ArrayIterator<TSrc>(source, action, threads);
140 return iter.Promise;
140 return iter.Promise;
141 }
141 }
142
142
143 public static IPromise<TDst[]> ChainedMap<TSrc, TDst>(this TSrc[] source, ChainedOperation<TSrc, TDst> transform, int threads) {
143 public static IPromise<TDst[]> ChainedMap<TSrc, TDst>(this TSrc[] source, ChainedOperation<TSrc, TDst> transform, int threads) {
144 if (source == null)
144 if (source == null)
145 throw new ArgumentNullException("source");
145 throw new ArgumentNullException("source");
146 if (transform == null)
146 if (transform == null)
147 throw new ArgumentNullException("transform");
147 throw new ArgumentNullException("transform");
148 if (threads <= 0)
148 if (threads <= 0)
149 throw new ArgumentOutOfRangeException("Threads number must be greater then zero");
149 throw new ArgumentOutOfRangeException("Threads number must be greater then zero");
150
150
151 if (source.Length == 0)
151 if (source.Length == 0)
152 return Promise<TDst[]>.ResultToPromise(new TDst[0]);
152 return Promise<TDst[]>.ResultToPromise(new TDst[0]);
153
153
154 var promise = new Promise<TDst[]>();
154 var promise = new Promise<TDst[]>();
155 var res = new TDst[source.Length];
155 var res = new TDst[source.Length];
156 var pending = source.Length;
156 var pending = source.Length;
157
157
158 var semaphore = new Semaphore(threads, threads);
158 var semaphore = new Semaphore(threads, threads);
159
159
160 AsyncPool.InvokeNewThread(() => {
160 AsyncPool.InvokeNewThread(() => {
161 for (int i = 0; i < source.Length; i++) {
161 for (int i = 0; i < source.Length; i++) {
162 if(promise.IsResolved)
162 if(promise.IsResolved)
163 break; // stop processing in case of error or cancellation
163 break; // stop processing in case of error or cancellation
164 var idx = i;
164 var idx = i;
165 semaphore.WaitOne();
165 semaphore.WaitOne();
166 try {
166 try {
167 var p1 = transform(source[i]);
167 var p1 = transform(source[i]);
168 p1.Anyway(() => semaphore.Release());
168 p1.Anyway(() => semaphore.Release());
169 p1.Cancelled(() => semaphore.Release());
169 p1.Cancelled(() => semaphore.Release());
170 p1.Then(
170 p1.Then(
171 x => {
171 x => {
172 res[idx] = x;
172 res[idx] = x;
173 var left = Interlocked.Decrement(ref pending);
173 var left = Interlocked.Decrement(ref pending);
174 if (left == 0)
174 if (left == 0)
175 promise.Resolve(res);
175 promise.Resolve(res);
176 },
176 },
177 e => promise.Reject(e)
177 e => promise.Reject(e)
178 );
178 );
179
179
180 } catch (Exception e) {
180 } catch (Exception e) {
181 promise.Reject(e);
181 promise.Reject(e);
182 }
182 }
183 }
183 }
184 return 0;
184 return 0;
185 });
185 });
186
186
187 return promise.Anyway(() => semaphore.Dispose());
187 return promise.Anyway(() => semaphore.Dispose());
188 }
188 }
189
189
190 }
190 }
191 }
191 }
@@ -1,50 +1,71
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.Snapshot();
18
18
19 ThreadPool.QueueUserWorkItem(param => {
19 ThreadPool.QueueUserWorkItem(param => {
20 TraceContext.Transfer(caller);
20 TraceContext.Fork(caller);
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 }
26 });
26 });
27
27
28 return p;
28 return p;
29 }
29 }
30
30
31 public static IPromise<T> InvokeNewThread<T>(Func<T> func) {
31 public static IPromise<T> InvokeNewThread<T>(Func<T> func) {
32 var p = new Promise<T>();
32 var p = new Promise<T>();
33
33
34 var caller = TraceContext.Snapshot();
34 var caller = TraceContext.Snapshot();
35
35
36 var worker = new Thread(() => {
36 var worker = new Thread(() => {
37 TraceContext.Transfer(caller);
37 TraceContext.Fork(caller);
38 try {
38 try {
39 p.Resolve(func());
39 p.Resolve(func());
40 } catch (Exception e) {
40 } catch (Exception e) {
41 p.Reject(e);
41 p.Reject(e);
42 }
42 }
43 });
43 });
44 worker.IsBackground = true;
44 worker.IsBackground = true;
45 worker.Start();
45 worker.Start();
46
46
47 return p;
47 return p;
48 }
48 }
49
50
51 public static IPromiseBase InvokeNewThread(Action func) {
52 var p = new Promise<object>();
53
54 var caller = TraceContext.Snapshot();
55
56 var worker = new Thread(() => {
57 TraceContext.Fork(caller);
58 try {
59 func();
60 p.Resolve();
61 } catch (Exception e) {
62 p.Reject(e);
63 }
64 });
65 worker.IsBackground = true;
66 worker.Start();
67
68 return p;
49 }
69 }
50 }
70 }
71 }
General Comments 0
You need to be logged in to leave comments. Login now