##// END OF EJS Templates
improved tracing...
cin -
r40:fe33f4e02ad5 default
parent child
Show More
@@ -0,0 +1,37
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Web;
5
6 namespace Implab {
7 /// <summary>
8 /// ΠšΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ ΡΠ²Π»ΡΡŽΡ‚ΡΡ состовными ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°ΠΌΠΈ, ΠΈΠΌΠ΅ΡŽΡ‚ Π΄Π΅Ρ‚Π΅Ρ€ΠΌΠΈΠ½ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹ΠΉ ΠΏΠ΅Ρ€ΠΈΠΎΠ΄ ΠΆΠΈΠ·Π½ΠΈ, автоматичСски ΠΎΡΠ²ΠΎΠ±ΠΎΠΆΠ΄Π°ΡŽΡ‚ рСсурсы входящиС Π² Π½ΠΈΡ….
9 /// </summary>
10 /// <remarks>ΠšΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π° управляСт Π²Ρ€Π΅ΠΌΠ΅Π½Π΅ΠΌ ΠΆΠΈΠ·Π½ΠΈ Π²ΠΊΠ»ΡŽΡ‡Π΅Π½Π½Ρ‹Ρ… Π² Π½Π΅Π΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚</remarks>
11 public class Component: Disposable {
12 LinkedList<IDisposable> m_components = new LinkedList<IDisposable>();
13
14 /// <summary>
15 /// ΠšΠΎΠ»Π»Π΅ΠΊΡ†ΠΈΡ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚, ΠΈΠ· ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… состоит тСкущая ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°.
16 /// </summary>
17 public ICollection<IDisposable> Components {
18 get {
19 AssertNotDisposed();
20 return m_components;
21 }
22 }
23
24 /// <summary>
25 /// ΠžΡΠ²ΠΎΠ±ΠΎΠΆΠ΄Π°Π΅Ρ‚ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹, входящиС Π² состав Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹.
26 /// </summary>
27 /// <param name="disposing">ΠŸΡ€ΠΈΠ·Π½Π°ΠΊ Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎ происходит освобоТдСниС рСсурсов.</param>
28 protected override void Dispose(bool disposing) {
29 if (disposing) {
30 foreach (var item in m_components)
31 item.Dispose();
32 m_components.Clear();
33 }
34 base.Dispose(disposing);
35 }
36 }
37 } No newline at end of file
@@ -0,0 +1,12
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5
6 namespace Implab.Diagnostics {
7 public struct EventText {
8 public int indent;
9
10 public string content;
11 }
12 }
@@ -0,0 +1,10
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5
6 namespace Implab.Diagnostics {
7 public interface IEventTextFormatter<in TEvent> {
8 EventText Format(TraceContext context, TEvent data);
9 }
10 }
@@ -0,0 +1,44
1 using System;
2 using System.Collections.Generic;
3 using System.IO;
4 using System.Linq;
5 using System.Text;
6
7 namespace Implab.Diagnostics {
8 public class TextFileListener: TextListenerBase {
9 readonly TextWriter m_textWriter;
10
11 public TextFileListener(string fileName) {
12 m_textWriter = File.CreateText(fileName);
13
14 m_textWriter.WriteLine("LOG {0}", DateTime.Now);
15 Register(this);
16 }
17
18 protected override void WriteEntry(TraceContext context, EventText text) {
19 var msg = new StringBuilder();
20 for (int i = 0; i < text.indent; i++)
21 msg.Append(" ");
22 msg.AppendFormat("[{0}]: {1}", context.ThreadId, text.content);
23
24 lock (m_textWriter) {
25 if (!IsDisposed) {
26 m_textWriter.WriteLine(msg.ToString());
27 m_textWriter.Flush();
28 }
29 }
30 }
31
32
33 protected override void Dispose(bool disposing) {
34 base.Dispose(disposing);
35 if (disposing) {
36 lock (m_textWriter) {
37 Safe.Dispose(m_textWriter);
38 }
39 }
40 }
41
42
43 }
44 }
@@ -0,0 +1,99
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5
6 namespace Implab.Diagnostics {
7 public abstract class TextListenerBase : ServiceLocator, IEventTextFormatter<object>, IEventTextFormatter<TraceEvent> {
8
9 readonly Dictionary<object, Action> m_subscriptions = new Dictionary<object, Action>();
10
11 protected TextListenerBase() {
12 Register(this);
13 }
14
15 public void Subscribe(Type eventType) {
16 if (eventType == null)
17 throw new ArgumentNullException("eventType");
18 GetType().GetMethod("Subscribe", new Type[0]).MakeGenericMethod(eventType).Invoke(this, null);
19 }
20
21 public void Subscribe<TEvent>() {
22 Subscribe<TEvent>(LogChannel<TEvent>.Default);
23 }
24
25 public void Subscribe<TEvent>(LogChannel<TEvent> channel) {
26 if (channel == null)
27 throw new ArgumentNullException("channel");
28
29 lock (m_subscriptions) {
30 AssertNotDisposed();
31
32 var formatter = GetService<IEventTextFormatter<TEvent>>();
33
34 EventHandler<ValueEventArgs<TEvent>> handler = (sender, args) => {
35 WriteEntry((TraceContext)sender, formatter.Format((TraceContext)sender, args.Value));
36 };
37
38 if (m_subscriptions.ContainsKey(channel))
39 return;
40
41 channel.Events += handler;
42
43 Action unsubscribe = () => {
44 channel.Events -= handler;
45 };
46
47 m_subscriptions.Add(channel, unsubscribe);
48 }
49 }
50
51 public void Unsubscribe<TEvent>(LogChannel<TEvent> channel) {
52 if (channel == null)
53 throw new ArgumentNullException("channel");
54
55 lock (m_subscriptions) {
56 Action subscription;
57 if (m_subscriptions.TryGetValue(channel, out subscription)) {
58 subscription();
59 m_subscriptions.Remove(channel);
60 }
61 }
62 }
63
64 public void UnsubscribeAll() {
65 lock (m_subscriptions) {
66 foreach (var subscription in m_subscriptions.Values)
67 subscription();
68 m_subscriptions.Clear();
69 }
70 }
71
72 protected abstract void WriteEntry(TraceContext context, EventText text);
73
74 public EventText Format(TraceContext context, object data) {
75 return new EventText {
76 indent = context.CurrentOperation.Level,
77 content = data.ToString()
78 };
79 }
80
81 public EventText Format(TraceContext context, TraceEvent data) {
82 var level = context.CurrentOperation.Level;
83 if (data.EventType == TraceEventType.OperationCompleted || data.EventType == TraceEventType.OperationStarted)
84 level--;
85
86 return new EventText {
87 indent = level,
88 content = data.ToString()
89 };
90 }
91
92 protected override void Dispose(bool disposing) {
93 if (disposing) {
94 UnsubscribeAll();
95 }
96 base.Dispose(disposing);
97 }
98 }
99 }
@@ -0,0 +1,46
1 using System;
2 using System.Collections.Generic;
3 using System.Diagnostics;
4 using System.Linq;
5 using System.Web;
6
7 namespace Implab {
8 public class Disposable : IDisposable {
9
10 bool m_disposed;
11
12 public event EventHandler Disposed;
13
14 public bool IsDisposed {
15 get { return m_disposed; }
16 }
17
18 protected void AssertNotDisposed() {
19 if (m_disposed)
20 throw new ObjectDisposedException(this.ToString());
21 }
22
23 protected virtual void Dispose(bool disposing) {
24 if (disposing && !m_disposed) {
25 m_disposed = true;
26
27 EventHandler temp = Disposed;
28 if (temp != null)
29 temp(this,EventArgs.Empty);
30 }
31 }
32 public void Dispose() {
33 Dispose(true);
34 GC.SuppressFinalize(this);
35 }
36
37 protected virtual void ReportObjectLeaks() {
38 Trace.TraceWarning("The object is marked as disposable but isn't disposed properly: {0}", this);
39 }
40
41 ~Disposable() {
42 Dispose(false);
43 ReportObjectLeaks();
44 }
45 }
46 } No newline at end of file
@@ -0,0 +1,12
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6
7 namespace Implab {
8 public interface IServiceLocator: IServiceProvider {
9 T GetService<T>();
10 bool TryGetService<T>(out T service);
11 }
12 }
@@ -0,0 +1,209
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Web;
5
6 namespace Implab {
7 /// <summary>
8 /// ΠšΠΎΠ»Π»Π΅ΠΊΡ†ΠΈΡ сСрвисов, позволяСт Ρ€Π΅Π³ΠΈΡΡ‚Ρ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π°Ρ‚ΡŒ сСрвисы.
9 /// </summary>
10 public class ServiceLocator: Component, IServiceLocator, IServiceProvider {
11 // запись ΠΎΠ± сСрвисС
12 struct ServiceEntry {
13 public object service; // сСрвис
14 public bool shared; // ΠΏΡ€ΠΈΠ·Π½Π°ΠΊ Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎ сСрвис НЕ Π½ΡƒΠΆΠ½ΠΎ ΠΎΡΠ²ΠΎΠ±ΠΎΠΆΠ΄Π°Ρ‚ΡŒ
15 public Func<object> activator; // Π°ΠΊΡ‚ΠΈΠ²Π°Ρ‚ΠΎΡ€ сСрвиса ΠΏΡ€ΠΈ ΠΏΠ΅Ρ€Π²ΠΎΠΌ ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠΈ
16 public List<Type> associated; // ссылки Π½Π° Ρ‚Π΅ΠΊΡƒΡ‰ΡƒΡŽ запись
17 public Type origin; // ссылка Π½Π° ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π»ΡŒΠ½ΡƒΡŽ запись ΠΎ сСрвисС
18 }
19
20 // ΡΠ»ΠΎΠ²Π°Ρ€ΡŒ ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΡ… сСрвисов
21 Dictionary<Type, ServiceEntry> m_services = new Dictionary<Type,ServiceEntry>();
22
23 /// <summary>
24 /// ΠŸΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‰ΠΈΠΉ сСрвис <typeparamref name="T"/>.
25 /// </summary>
26 /// <typeparam name="T">Π’ΠΈΠΏ Π·Π°ΠΏΡ€Π°ΡˆΠΈΠ²Π°Π΅ΠΌΠΎΠ³ΠΎ сСрвиса</typeparam>
27 /// <returns>ΠžΠ±ΡŠΠ΅ΠΊΡ‚, Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΡŽΡ‰ΠΈΠΉ сСрвис</returns>
28 /// <exception cref="KeyNotFoundException">БСрвис Π½Π΅ зарСгистрирован</exception>
29 public T GetService<T>() {
30 return (T)GetService(typeof(T));
31 }
32
33
34 /// <summary>
35 /// ΠŸΡ‹Ρ‚Π°Π΅Ρ‚ΡΡ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹ΠΉ сСрвис, Π² случаС, Ссли ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π° Π½Π΅ прСдоставляСт Ρ‚Ρ€Π΅Π±ΡƒΠ΅ΠΌΡ‹ΠΉ сСрвис
36 /// Π½Π΅ Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π΅Ρ‚ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠΉ.
37 /// </summary>
38 /// <typeparam name="T">Π’ΠΈΠΏ Ρ‚Ρ€Π΅Π±ΡƒΠ΅ΠΌΠΎΠ³ΠΎ сСрвиса.</typeparam>
39 /// <param name="service">ΠžΠ±ΡŠΠ΅ΠΊΡ‚ Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΡŽΡ‰ΠΈΠΉ сСрвис, ΠΈΠ»ΠΈ <c>default(T)</c> Ссли Ρ‚Π°ΠΊΠΎΠ²ΠΎΠ³ΠΎ Π½Π΅Ρ‚.</param>
40 /// <returns><c>true</c> - сСрвис Π½Π°ΠΉΠ΄Π΅Π½, <c>false</c> - сСрвис Π½Π΅ зарСгистрирован.</returns>
41 public bool TryGetService<T>(out T service) {
42 AssertNotDisposed();
43
44 try {
45 service = GetService<T>();
46 return true;
47 } catch(KeyNotFoundException) {
48 service = default(T);
49 return false;
50 }
51 }
52
53 /// <summary>
54 /// ΠŸΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‰ΠΈΠΉ сСрвис <paramref name="serviceType"/>
55 /// </summary>
56 /// <param name="serviceType">Π’ΠΈΠΏ Π·Π°ΠΏΡ€Π°ΡˆΠΈΠ²Π°Π΅ΠΌΠΎΠ³ΠΎ сСрвиса</param>
57 /// <returns>ΠžΠ±ΡŠΠ΅ΠΊΡ‚, Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΡŽΡ‰ΠΈΠΉ сСрвис</returns>
58 /// <exception cref="KeyNotFoundException">БСрвис Π½Π΅ зарСгистрирован</exception>
59 public object GetService(Type serviceType) {
60 if (serviceType == null)
61 throw new ArgumentNullException("serviceType");
62 AssertNotDisposed();
63
64 ServiceEntry se;
65 if (!m_services.TryGetValue(serviceType, out se)) {
66 // ΠΈΡ‰Π΅ΠΌ Π±Π»ΠΈΠΆΠ°ΠΉΡ‰ΠΈΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚, Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΡŽΡ‰ΠΈΠΉ Π½ΡƒΠΆΠ½Ρ‹ΠΉ сСрвис
67 Type pt = null;
68 foreach (var t in m_services.Keys)
69 if (serviceType.IsAssignableFrom(t) && (pt == null || t.IsAssignableFrom(pt)))
70 pt = t;
71 if (pt == null)
72 throw new ApplicationException(String.Format("{0} doesn't provide {1} service",this,serviceType));
73
74 var pe = m_services[pt];
75
76 // найдСнная запись ΠΌΠΎΠΆΠ΅Ρ‚ ΡΡΡ‹Π»Π°Ρ‚ΡŒΡΡ Π½Π° ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π»ΡŒΠ½ΡƒΡŽ запись с сСрвисом
77 if(pe.origin != null) {
78 pt = pe.origin;
79 pe = m_services[pt];
80 }
81
82 // добавляСм список с ΠΎΠ±Ρ€Π°Ρ‚Π½Ρ‹ΠΌΠΈ ссылками
83 if (pe.associated == null)
84 pe.associated = new List<Type>();
85
86 pe.associated.Add(serviceType);
87
88 // обновляСм Ρ€ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΡΠΊΡƒΡŽ запись
89 m_services[pt] = pe;
90
91 // создаСм запись со ссылкой
92 se = new ServiceEntry {
93 service = pe.service,
94 origin = pt,
95 shared = true // ΠΏΡ€Π΅Π΄ΠΎΡ‚Π²Ρ€Π°Ρ‰Π°Π΅ΠΌ мноТСствСнныС ΠΏΠΎΠΏΡ‹Ρ‚ΠΊΠΈ освобоТдСния
96 };
97
98 m_services[serviceType] = se;
99 }
100
101 // запись содСрТит Π² сСбС ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎ сСрвисС
102 if (se.service != null)
103 return se.service;
104
105 // тСкущая запись являСтся ссылкой
106 if (se.origin != null) {
107 se.service = GetService(se.origin);
108 m_services[serviceType] = se;
109 return se.service;
110 }
111
112 // тСкущая запись Π½Π΅ являСтся ссылкой ΠΈ Π½Π΅ ΠΈΠΌΠ΅Π΅Ρ‚ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ ΠΎ сСрвисС
113 // ΠΎΠ½Π° Π΄ΠΎΠ»ΠΆΠ½Π° ΡΠΎΠΆΠ΅Ρ€ΠΆΠ°Ρ‚ΡŒ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎΠ± Π°ΠΊΡ‚ΠΈΠ²Π°Ρ†ΠΈΠΈ
114 if (se.activator != null) {
115 se.service = se.activator();
116
117 m_services[serviceType] = se;
118
119 return se.service;
120 }
121
122 throw new Exception("Unable to create a service instance");
123 }
124
125 /// <summary>
126 /// РСгистрируСт Ρ„Π°Π±Ρ€ΠΈΠΊΡƒ для Π°ΠΊΡ‚ΠΈΠ²Π°Ρ†ΠΈΠΈ сСрвиса ΠΏΠΎ ΠΏΠ΅Ρ€Π²ΠΎΠΌΡƒ Ρ‚Ρ€Π΅Π±ΠΎΠ²Π°Π½ΠΈΡŽ.
127 /// </summary>
128 /// <typeparam name="T">Π’ΠΈΠΏ рСгистрируСмого сСрвиса.</typeparam>
129 /// <param name="activator">Π€Π°Π±Ρ€ΠΈΠΊΠ° для создания/получСния ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°, ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‰Π΅Π³ΠΎ сСрвис.</param>
130 /// <exception cref="InvalidOperationException">Π£ΠΊΠ°Π·Π°Π½Π½Ρ‹ΠΉ сСрвис ΡƒΠΆΠ΅ зарСгистрирован.</exception>
131 /// <remarks>ΠŸΡ€ΠΈ освобоТдСнии сСрвис-Π»ΠΎΠΊΠ°Ρ‚ΠΎΡ€Π°, сСрвисы ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π½Ρ‹Π΅ Π² Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅ Π°ΠΊΡ‚ΠΈΠ²Π°Ρ†ΠΈΠΈ Ρ‚Π°ΠΊΠΆΠ΅ Π±ΡƒΠ΄ΡƒΡ‚ освобоТдСны.</remarks>
132 public void Register<T>(Func<T> activator) {
133 if (activator == null)
134 throw new ArgumentNullException("activator");
135
136 AssertNotDisposed();
137
138 Unregister(typeof(T));
139
140 m_services[typeof(T)] = new ServiceEntry {
141 activator = () => activator() as object
142 };
143 }
144
145 /// <summary>
146 /// РСгистрируСт ΠΎΠ±ΡŠΠ΅ΠΊΡ‚, ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‰ΠΈΠΉ сСрвис.
147 /// </summary>
148 /// <typeparam name="T">Π’ΠΈΠΏ рСгистрируСмого сСрвиса.</typeparam>
149 /// <param name="service">ΠžΠ±ΡŠΠ΅ΠΊΡ‚, ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‰ΠΈΠΉ сСрвис.</param>
150 /// <exception cref="InvalidOperationException">Π£ΠΊΠ°Π·Π°Π½Π½Ρ‹ΠΉ сСрвис ΡƒΠΆΠ΅ зарСгистрирован.</exception>
151 /// <remarks>БСрвис-Π»ΠΎΠΊΠ°Ρ‚ΠΎΡ€ΠΎΠΌ Π½Π΅ управляСт Π²Ρ€Π΅ΠΌΠ΅Π½Π΅ΠΌ ΠΆΠΈΠ·Π½ΠΈ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° для зарСгистрированного сСрвиса.</remarks>
152 public void Register<T>(T service) {
153 Register(service, true);
154 }
155
156 /// <summary>
157 /// РСгистрируСт ΠΎΠ±ΡŠΠ΅ΠΊΡ‚, ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‰ΠΈΠΉ сСрвис.
158 /// </summary>
159 /// <typeparam name="T">Π’ΠΈΠΏ рСгистрируСмого сСрвиса.</typeparam>
160 /// <param name="service">ΠžΠ±ΡŠΠ΅ΠΊΡ‚, ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‰ΠΈΠΉ сСрвис.</param>
161 /// <param name="shared">ΠŸΡ€ΠΈΠ·Π½Π°ΠΊ Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ являСтся раздСляСмым ΠΈ сСрвис-Π»ΠΎΠΊΠ°Ρ‚ΠΎΡ€ Π½Π΅ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π΅Π³ΠΎ ΠΎΡΠ²ΠΎΠ±ΠΎΠΆΠ΄Π°Ρ‚ΡŒ.</param>
162 /// <exception cref="InvalidOperationException">Π£ΠΊΠ°Π·Π°Π½Π½Ρ‹ΠΉ сСрвис ΡƒΠΆΠ΅ зарСгистрирован.</exception>
163 public void Register<T>(T service, bool shared) {
164 if (service == null)
165 throw new ArgumentNullException("service");
166
167 AssertNotDisposed();
168
169 Unregister(typeof(T));
170
171 m_services[typeof(T)] = new ServiceEntry { service = service, shared = shared };
172 }
173
174 public void Unregister(Type serviceType) {
175 if (serviceType == null)
176 throw new ArgumentNullException("serviceType");
177
178 AssertNotDisposed();
179
180 ServiceEntry se;
181 if (m_services.TryGetValue(serviceType, out se)) {
182 // освобоТдаСм рСсурсы
183 if (se.service != null && !se.shared)
184 ((IDisposable)se.service).Dispose();
185 m_services.Remove(serviceType);
186
187 // ΡƒΠ±ΠΈΡ€Π°Π΅ΠΌ связанныС записи
188 if (se.associated != null)
189 foreach (var item in se.associated)
190 m_services.Remove(item);
191 }
192 }
193
194 /// <summary>
195 /// ΠžΡΠ²ΠΎΠ±ΠΎΠΆΠ΄Π°Π΅Ρ‚ зарСгистрированныС сСрвисы (ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ трСбуСтся ΠΎΡΠ²ΠΎΠ±ΠΎΠΈΡ‚ΡŒ).
196 /// </summary>
197 /// <param name="disposing">ΠŸΡ€ΠΈΠ·Π°Π½Π°ΠΊ Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎ Π½ΡƒΠΆΠ½ΠΎ ΠΎΡΠ²ΠΎΠ±ΠΎΠ΄ΠΈΡ‚ΡŒ рСсурсы.</param>
198 protected override void Dispose(bool disposing) {
199 if (disposing) {
200
201 foreach (var entry in m_services.Values)
202 if (!entry.shared && entry.service is IDisposable)
203 ((IDisposable)entry.service).Dispose();
204
205 }
206 base.Dispose(disposing);
207 }
208 }
209 } No newline at end of file
@@ -1,37 +1,24
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 {
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 void Subscribe() {
11 protected override void WriteEntry(TraceContext context, EventText text) {
12 LogChannel<TraceEvent>.Default.Events += Default_Events;
12 var msg = new StringBuilder();
13 }
14
15 public void Unsubscribe() {
16 LogChannel<TraceEvent>.Default.Events -= Default_Events;
17 }
18
13
19 void Default_Events(object sender, ValueEventArgs<TraceEvent> e) {
14 for (int i = 0; i < text.indent; i++)
20 LogEvent((TraceContext)sender, e.Value);
21 }
22
23 void LogEvent(TraceContext context, TraceEvent evt) {
24 var msg = new StringBuilder();
25 for (int i = 0; i < context.CurrentOperation.Level; i++)
26 msg.Append(" ");
15 msg.Append(" ");
27 msg.Append(evt.EventType);
16 msg.AppendFormat("[{0}]: {1}", context.ThreadId, text.content);
28 msg.AppendFormat("[{0}]: ",context.ThreadId);
29 msg.Append(evt.Message);
30
17
31 lock (_consoleLock) {
18 lock (_consoleLock) {
32 Console.ForegroundColor = (ConsoleColor)(context.ThreadId % 15 + 1);
19 Console.ForegroundColor = (ConsoleColor)(context.ThreadId % 15 + 1);
33 Console.WriteLine(msg.ToString());
20 Console.WriteLine(msg.ToString());
34 }
21 }
35 }
22 }
36 }
23 }
37 }
24 }
@@ -1,97 +1,163
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>
10 /// ΠšΠΎΠ½Ρ‚Π΅ΠΊΡΡ‚ трассировки, привязываСтся ΠΊ ΠΏΠΎΡ‚ΠΎΠΊΡƒ ΠΈ содСрТит Π² сСбС ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎ стСкС логичСских ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ.
11 /// </summary>
12 /// <remarks>
13 /// ΠšΠΎΠ½Ρ‚Π΅ΠΊΡΡ‚ трассировки пСрСдаСтся ΡΠ»ΡƒΡˆΠ°Ρ‚Π΅Π»ΡΠΌ событий для опрСдСлСния мСста, Π³Π΄Π΅ Π²ΠΎΠ·Π½ΠΈΠΊΠ»ΠΎ событиС.
14 /// </remarks>
9 public class TraceContext {
15 public class TraceContext {
10 LogicalOperation m_currentOperation;
16 LogicalOperation m_currentOperation;
11 readonly LogicalOperation m_traceBound;
17 readonly LogicalOperation m_bound;
12 readonly int m_threadId;
18 readonly int m_threadId;
13 readonly TraceContext m_parent;
14
15 readonly static object _consoleLock = new object();
16
19
17 [ThreadStatic]
20 [ThreadStatic]
18 static TraceContext _current;
21 static TraceContext _current;
19
22
23 /// <summary>
24 /// Π’Π΅ΠΊΡƒΡ‰ΠΈΠΉ контСкст трассировки для ΠΏΠΎΡ‚ΠΎΠΊΠ°, создаСтся астоматичСски ΠΏΡ€ΠΈ ΠΏΠ΅Ρ€Π²ΠΎΠΌ ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠΈ.
25 /// </summary>
20 public static TraceContext Current {
26 public static TraceContext Current {
21 get {
27 get {
22 if (_current == null)
28 if (_current == null)
23 _current = new TraceContext();
29 _current = new TraceContext();
24 return _current;
30 return _current;
25 }
31 }
26 }
32 }
27
33
28 TraceContext(TraceContext context) {
34 TraceContext(TraceContext context) {
29 if (context == null)
35 if (context == null)
30 throw new ArgumentNullException("context");
36 throw new ArgumentNullException("context");
31
37
32 m_parent = context;
33 m_currentOperation = context.CurrentOperation;
38 m_currentOperation = context.CurrentOperation;
34 m_traceBound = context.CurrentOperation;
39 m_bound = context.CurrentOperation;
35 m_threadId = Thread.CurrentThread.ManagedThreadId;
40 m_threadId = Thread.CurrentThread.ManagedThreadId;
36
37 LogEvent(TraceEventType.Transfer, "FORK {0}", context.ThreadId);
38 }
41 }
39
42
40 TraceContext() {
43 TraceContext() {
41 m_currentOperation = new LogicalOperation();
44 m_currentOperation = new LogicalOperation();
42 m_traceBound = m_currentOperation;
45 m_bound = m_currentOperation;
43 m_threadId = Thread.CurrentThread.ManagedThreadId;
46 m_threadId = Thread.CurrentThread.ManagedThreadId;
44 }
47 }
45
48
49 /// <summary>
50 /// ΠŸΡ€ΠΈ нСобходимости ΠΊΠΎΠΏΠΈΡ€ΡƒΠ΅Ρ‚ состояниС контСкста трассивровки Π² Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΉ ΠΏΠΎΡ‚ΠΎΠΊ.
51 /// </summary>
52 /// <param name="from">Π˜ΡΡ…ΠΎΠ΄Π½Ρ‹ΠΉ контСкст трассировки, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ пСрСдаСтся.</param>
53 /// <remarks>
54 /// <para>
55 /// ΠšΠΎΠΏΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ происходит Π·Π° счСт создания Π½ΠΎΠ²ΠΎΠ³ΠΎ контСкста трассировки ΠΈ Π·Π°ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ΠΌ Π΅Π³ΠΎ
56 /// состояния ΠΈΠ· ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½ΠΎΠ³ΠΎ контСкста. ΠŸΡ€ΠΈ этом копируСтся стСк ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ, ΠΎΠ΄Π½Π°ΠΊΠΎ Π² Π½ΠΎΠ²ΠΎΠΌ
57 /// контСкстС Ρ€Π°Π½Π΅Π΅ Π½Π°Ρ‡Π°Ρ‚Ρ‹Π΅ логичСскиС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ Π½Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½Ρ‹.
58 /// </para>
59 /// <para>
60 /// Если ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Π° состояния ΡΠΎΡΡ‚ΠΎΡΠ»Π°ΡΡŒ, Ρ‚ΠΎ вызываСтся событиС трассировки <see cref="TraceEventType.Transfer"/>.
61 /// </para>
62 /// </remarks>
46 public static void Transfer(TraceContext from) {
63 public static void Transfer(TraceContext from) {
47 _current = from == null ? new TraceContext() : new TraceContext(from);
64 if (_current == from)
48 }
65 return;
49
66 if (from != null) {
50 public TraceContext ParentContext {
67 var context = new TraceContext(from);
51 get {
68 context.LogEvent(TraceEventType.Transfer, "[{0}]-->[{1}]",from.ThreadId, context.ThreadId);
52 return m_parent;
69 _current = context;
70 } else {
71 _current = new TraceContext();
53 }
72 }
54 }
73 }
55
74
75 /// <summary>
76 /// Π‘ΠΎΠ·Π΄Π°Π΅Ρ‚ ΠΏΠΎΡΡ‚ΠΎΡΠ½Π½ΡƒΡŽ копию Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π³ΠΎ контСкста, Π΄Π°Π½Π½ΡƒΡŽ копию ΠΌΠΎΠΆΠ½ΠΎ Ρ…Ρ€Π°Π½ΠΈΡ‚ΡŒ ΠΈ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ для ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ Ρ‡Π΅Ρ€Π΅Π· <see cref="Transfer(TraceContext)"/>
77 /// </summary>
78 /// <returns>Копия Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π³ΠΎ контСкста трассировки ΠΈΠ»ΠΈ <c>null</c> Ссли Ρ‚Π°ΠΊΠΎΠ²ΠΎΠΉ Π½Π΅ Π±Ρ‹Π» создан.</returns>
79 public static TraceContext Snapshot() {
80 return _current == null ? null : new TraceContext(_current);
81 }
82
83 /// <summary>
84 /// ВыполняСт ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½ΠΎΠ΅ дСйствиС Π² ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΌ контСкстС трассировки, ΠΏΠΎ ΠΎΠΊΠΎΠ½Ρ‡Π°Π½ΠΈΠΈ восстанавливаСт ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΠΈΠΉ контСкст трассировки ΠΏΠΎΡ‚ΠΎΠΊΠ°.
85 /// </summary>
86 /// <param name="action"></param>
87 public void Invoke(Action action) {
88 if (action == null)
89 throw new ArgumentNullException("action");
90 var old = _current;
91 Transfer(this);
92 try {
93 action();
94 } finally {
95 _current = old;
96 }
97 }
98
99 /// <summary>
100 /// ВСкущая логичСская опСрация.
101 /// </summary>
56 public LogicalOperation CurrentOperation {
102 public LogicalOperation CurrentOperation {
57 get {
103 get {
58 return m_currentOperation;
104 return m_currentOperation;
59 }
105 }
60 }
106 }
61
107
62 public LogicalOperation TraceBound {
108 /// <summary>
109 /// ΠžΠΏΠ΅Ρ€Π°Ρ†ΠΈΡ Π½ΠΈΠΆΠ΅ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ нСльзя ΠΎΠΏΡƒΡΠΊΠ°Ρ‚ΡŒΡΡ Π² стСкС логичСских ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ, Ρ‚.Π΅. ΠΎΠ½Π° Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½Π° Π² Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌ контСкстС.
110 /// </summary>
111 public LogicalOperation BoundOperation {
63 get {
112 get {
64 return m_traceBound;
113 return m_bound;
65 }
114 }
66 }
115 }
67
116
117 /// <summary>
118 /// ΠŸΠΎΡ‚ΠΎΠΊ, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ создан контСкст трассировки.
119 /// </summary>
68 public int ThreadId {
120 public int ThreadId {
69 get {
121 get {
70 return m_threadId;
122 return m_threadId;
71 }
123 }
72 }
124 }
73
125
126 /// <summary>
127 /// НачинаСт Π±Π΅Π·Ρ‹ΠΌΡΠ½Π½ΡƒΡŽ Π»ΠΎΠ³ΠΈΡ‡Π΅ΡΠΊΡƒΡŽ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ.
128 /// </summary>
74 public void StartLogicalOperation() {
129 public void StartLogicalOperation() {
75 StartLogicalOperation(null);
130 StartLogicalOperation(null);
76 }
131 }
77
132
133 /// <summary>
134 /// НачинаСт Π»ΠΎΠ³ΠΈΡ‡Π΅ΡΠΊΡƒΡŽ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ с ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹ΠΌ ΠΈΠΌΠ΅Π½Π΅ΠΌ. Бозданная опСрация Π±ΡƒΠ΄Π΅Ρ‚ Π΄ΠΎΠ±Π²Π°Π»Π΅Π½Π° Π² стСк логичСских ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ контСкста, Π·Π°Ρ‚Π΅ΠΌ Π±ΡƒΠ΄Π΅Ρ‚ создано ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΠ²ΡƒΡŽΡ‰Π΅Π΅ событиС.
135 /// </summary>
136 /// <param name="name">Имя Π½Π°Ρ‡ΠΈΠ½Π°Π΅ΠΌΠΎΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</param>
78 public void StartLogicalOperation(string name) {
137 public void StartLogicalOperation(string name) {
79 LogEvent(TraceEventType.OperationStarted, "{0}", name);
80 m_currentOperation = new LogicalOperation(name, m_currentOperation);
138 m_currentOperation = new LogicalOperation(name, m_currentOperation);
139 LogEvent(TraceEventType.OperationStarted, name);
81 }
140 }
82
141
142 /// <summary>
143 /// Π—Π°ΠΊΠ°Π½Ρ‡ΠΈΠ²Π°Π΅Ρ‚ Π»ΠΎΠ³ΠΈΡ‡Π΅ΡΠΊΡƒΡŽ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ Π½Π°Ρ‡Π°Ρ‚ΡƒΡŽ Π² Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌ контСкстС. ΠžΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, Π½Π°Ρ‡Π°Ρ‚Ρ‹Π΅ Π² Π΄Ρ€ΡƒΠ³ΠΈΡ… контСкстах Π½Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ Π·Π°ΠΊΠΎΠ½Ρ‡Π΅Π½Ρ‹ Π² Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌ контСкстС.
144 /// </summary>
145 /// <remarks>
146 /// ΠŸΡ€ΠΈ Π²Ρ‹Π·ΠΎΠ²Π΅ Π΄Π°Π½Π½ΠΎΠ³ΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄Π° создаСтся событиС ΠΆΡƒΡ€Π½Π°Π»Π° трассировки, Π»ΠΈΠ±ΠΎ ΠΎ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, Π»ΠΈΠ±ΠΎ ΠΎΠ± ошибки, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ данная опСрация
147 /// Π½Π°Ρ‡Π°Ρ‚Π° Π² Π΄Ρ€ΡƒΠ³ΠΎΠΌ контСкстС.
148 /// </remarks>
83 public void EndLogicalOperation() {
149 public void EndLogicalOperation() {
84 if (m_traceBound == m_currentOperation) {
150 if (m_bound == m_currentOperation) {
85 LogEvent(TraceEventType.Error, "Trying to end the operation which isn't belongs to current trace");
151 LogEvent(TraceEventType.Error, "Trying to end the operation which isn't belongs to current trace");
86 } else {
152 } else {
87 var op = m_currentOperation;
153 var op = m_currentOperation;
154 LogEvent(TraceEventType.OperationCompleted, "{0} {1} ms", op.Name, op.Duration);
88 m_currentOperation = m_currentOperation.Parent;
155 m_currentOperation = m_currentOperation.Parent;
89 LogEvent(TraceEventType.OperationCompleted, "{0} {1} ms", op.Name, op.Duration);
90 }
156 }
91 }
157 }
92
158
93 void LogEvent(TraceEventType type, string format, params object[] args) {
159 void LogEvent(TraceEventType type, string format, params object[] args) {
94 LogChannel<TraceEvent>.Default.LogEvent(this, TraceEvent.Create(type, format, args));
160 LogChannel<TraceEvent>.Default.LogEvent(this, TraceEvent.Create(type, format, args));
95 }
161 }
96 }
162 }
97 }
163 }
@@ -1,27 +1,31
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 TraceEvent {
7 public class TraceEvent {
8 public string Message {
8 public string Message {
9 get;
9 get;
10 private set;
10 private set;
11 }
11 }
12
12
13 public TraceEventType EventType {
13 public TraceEventType EventType {
14 get;
14 get;
15 private set;
15 private set;
16 }
16 }
17
17
18 public TraceEvent(TraceEventType type, string message) {
18 public TraceEvent(TraceEventType type, string message) {
19 EventType = type;
19 EventType = type;
20 Message = message;
20 Message = message;
21 }
21 }
22
22
23 public override string ToString() {
24 return String.Format("{0}: {1}", EventType, Message);
25 }
26
23 public static TraceEvent Create(TraceEventType type, string format, params object[] args) {
27 public static TraceEvent Create(TraceEventType type, string format, params object[] args) {
24 return new TraceEvent(type, String.Format(format, args));
28 return new TraceEvent(type, String.Format(format, args));
25 }
29 }
26 }
30 }
27 }
31 }
@@ -1,53 +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 /// Π–ΡƒΡ€Π½Π°Π» трассировки ΠΎΡ‚Ρ€Π°ΠΆΠ°Π΅Ρ‚ логичСский Ρ…ΠΎΠ΄ выполнСния ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ ΠΈ сущСствуСт всСгда, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ тСсно связан с
12 /// контСкстом трассировки.
11 /// </summary>
13 /// </summary>
12 public static class TraceLog {
14 public static class TraceLog {
13 [Conditional("TRACE")]
15 [Conditional("TRACE")]
14 public static void Transfer(TraceContext from) {
15 TraceContext.Transfer(from);
16 }
17
18 [Conditional("TRACE")]
19 public static void StartLogicalOperation() {
16 public static void StartLogicalOperation() {
20 TraceContext.Current.StartLogicalOperation();
17 TraceContext.Current.StartLogicalOperation();
21 }
18 }
22
19
23 [Conditional("TRACE")]
20 [Conditional("TRACE")]
24 public static void StartLogicalOperation(string name) {
21 public static void StartLogicalOperation(string name) {
25 TraceContext.Current.StartLogicalOperation(name);
22 TraceContext.Current.StartLogicalOperation(name);
26 }
23 }
27
24
28 [Conditional("TRACE")]
25 [Conditional("TRACE")]
29 public static void EndLogicalOperation() {
26 public static void EndLogicalOperation() {
30 TraceContext.Current.EndLogicalOperation();
27 TraceContext.Current.EndLogicalOperation();
31 }
28 }
32
29
33 [Conditional("TRACE")]
30 [Conditional("TRACE")]
34 public static void TraceInformation(string format, params object[] arguments) {
31 public static void TraceInformation(string format, params object[] arguments) {
35 LogChannel<TraceEvent>.Default.LogEvent(TraceEvent.Create(TraceEventType.Information, format, arguments));
32 LogChannel<TraceEvent>.Default.LogEvent(TraceEvent.Create(TraceEventType.Information, format, arguments));
36 }
33 }
37
34
38 [Conditional("TRACE")]
35 [Conditional("TRACE")]
39 public static void TraceWarning(string format, params object[] arguments) {
36 public static void TraceWarning(string format, params object[] arguments) {
40 LogChannel<TraceEvent>.Default.LogEvent(TraceEvent.Create(TraceEventType.Warning, format, arguments));
37 LogChannel<TraceEvent>.Default.LogEvent(TraceEvent.Create(TraceEventType.Warning, format, arguments));
41 }
38 }
42
39
43 [Conditional("TRACE")]
40 [Conditional("TRACE")]
44 public static void TraceError(string format, params object[] arguments) {
41 public static void TraceError(string format, params object[] arguments) {
45 LogChannel<TraceEvent>.Default.LogEvent(TraceEvent.Create(TraceEventType.Error, format, arguments));
42 LogChannel<TraceEvent>.Default.LogEvent(TraceEvent.Create(TraceEventType.Error, format, arguments));
46 }
43 }
47
44
48 [Conditional("TRACE")]
45 [Conditional("TRACE")]
49 public static void TraceError(Exception err) {
46 public static void TraceError(Exception err) {
50 TraceError("{0}", err);
47 TraceError("{0}", err);
51 }
48 }
52 }
49 }
53 }
50 }
@@ -1,63 +1,71
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 <ProductVersion>10.0.0</ProductVersion>
6 <ProductVersion>10.0.0</ProductVersion>
7 <SchemaVersion>2.0</SchemaVersion>
7 <SchemaVersion>2.0</SchemaVersion>
8 <ProjectGuid>{F550F1F8-8746-4AD0-9614-855F4C4B7F05}</ProjectGuid>
8 <ProjectGuid>{F550F1F8-8746-4AD0-9614-855F4C4B7F05}</ProjectGuid>
9 <OutputType>Library</OutputType>
9 <OutputType>Library</OutputType>
10 <RootNamespace>Implab</RootNamespace>
10 <RootNamespace>Implab</RootNamespace>
11 <AssemblyName>Implab</AssemblyName>
11 <AssemblyName>Implab</AssemblyName>
12 </PropertyGroup>
12 </PropertyGroup>
13 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
13 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
14 <DebugSymbols>true</DebugSymbols>
14 <DebugSymbols>true</DebugSymbols>
15 <DebugType>full</DebugType>
15 <DebugType>full</DebugType>
16 <Optimize>false</Optimize>
16 <Optimize>false</Optimize>
17 <OutputPath>bin\Debug</OutputPath>
17 <OutputPath>bin\Debug</OutputPath>
18 <DefineConstants>TRACE;DEBUG;</DefineConstants>
18 <DefineConstants>TRACE;DEBUG;</DefineConstants>
19 <ErrorReport>prompt</ErrorReport>
19 <ErrorReport>prompt</ErrorReport>
20 <WarningLevel>4</WarningLevel>
20 <WarningLevel>4</WarningLevel>
21 <ConsolePause>false</ConsolePause>
21 <ConsolePause>false</ConsolePause>
22 </PropertyGroup>
22 </PropertyGroup>
23 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
23 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
24 <DebugType>full</DebugType>
24 <DebugType>full</DebugType>
25 <Optimize>true</Optimize>
25 <Optimize>true</Optimize>
26 <OutputPath>bin\Release</OutputPath>
26 <OutputPath>bin\Release</OutputPath>
27 <ErrorReport>prompt</ErrorReport>
27 <ErrorReport>prompt</ErrorReport>
28 <WarningLevel>4</WarningLevel>
28 <WarningLevel>4</WarningLevel>
29 <ConsolePause>false</ConsolePause>
29 <ConsolePause>false</ConsolePause>
30 </PropertyGroup>
30 </PropertyGroup>
31 <ItemGroup>
31 <ItemGroup>
32 <Reference Include="System" />
32 <Reference Include="System" />
33 </ItemGroup>
33 </ItemGroup>
34 <ItemGroup>
34 <ItemGroup>
35 <Compile Include="Component.cs" />
35 <Compile Include="Diagnostics\ConsoleTraceListener.cs" />
36 <Compile Include="Diagnostics\ConsoleTraceListener.cs" />
37 <Compile Include="Diagnostics\EventText.cs" />
38 <Compile Include="Diagnostics\IEventTextFormatter.cs" />
36 <Compile Include="Diagnostics\LogChannel.cs" />
39 <Compile Include="Diagnostics\LogChannel.cs" />
37 <Compile Include="Diagnostics\LogicalOperation.cs" />
40 <Compile Include="Diagnostics\LogicalOperation.cs" />
41 <Compile Include="Diagnostics\TextFileListener.cs" />
42 <Compile Include="Diagnostics\TextListenerBase.cs" />
38 <Compile Include="Diagnostics\TraceLog.cs" />
43 <Compile Include="Diagnostics\TraceLog.cs" />
39 <Compile Include="Diagnostics\TraceContext.cs" />
44 <Compile Include="Diagnostics\TraceContext.cs" />
40 <Compile Include="Diagnostics\TraceEvent.cs" />
45 <Compile Include="Diagnostics\TraceEvent.cs" />
41 <Compile Include="Diagnostics\TraceEventType.cs" />
46 <Compile Include="Diagnostics\TraceEventType.cs" />
47 <Compile Include="Disposable.cs" />
42 <Compile Include="ICancellable.cs" />
48 <Compile Include="ICancellable.cs" />
43 <Compile Include="IProgressHandler.cs" />
49 <Compile Include="IProgressHandler.cs" />
44 <Compile Include="IProgressNotifier.cs" />
50 <Compile Include="IProgressNotifier.cs" />
45 <Compile Include="IPromise.cs" />
51 <Compile Include="IPromise.cs" />
46 <Compile Include="IPromiseBase.cs" />
52 <Compile Include="IPromiseBase.cs" />
53 <Compile Include="IServiceLocator.cs" />
47 <Compile Include="ITaskController.cs" />
54 <Compile Include="ITaskController.cs" />
48 <Compile Include="ManagedPromise.cs" />
55 <Compile Include="ManagedPromise.cs" />
49 <Compile Include="Parallels\DispatchPool.cs" />
56 <Compile Include="Parallels\DispatchPool.cs" />
50 <Compile Include="Parallels\ArrayTraits.cs" />
57 <Compile Include="Parallels\ArrayTraits.cs" />
51 <Compile Include="Parallels\MTQueue.cs" />
58 <Compile Include="Parallels\MTQueue.cs" />
52 <Compile Include="Parallels\WorkerPool.cs" />
59 <Compile Include="Parallels\WorkerPool.cs" />
60 <Compile Include="ServiceLocator.cs" />
53 <Compile Include="TaskController.cs" />
61 <Compile Include="TaskController.cs" />
54 <Compile Include="ProgressInitEventArgs.cs" />
62 <Compile Include="ProgressInitEventArgs.cs" />
55 <Compile Include="Properties\AssemblyInfo.cs" />
63 <Compile Include="Properties\AssemblyInfo.cs" />
56 <Compile Include="Promise.cs" />
64 <Compile Include="Promise.cs" />
57 <Compile Include="Parallels\AsyncPool.cs" />
65 <Compile Include="Parallels\AsyncPool.cs" />
58 <Compile Include="Safe.cs" />
66 <Compile Include="Safe.cs" />
59 <Compile Include="ValueEventArgs.cs" />
67 <Compile Include="ValueEventArgs.cs" />
60 </ItemGroup>
68 </ItemGroup>
61 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
69 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
62 <ItemGroup />
70 <ItemGroup />
63 </Project> No newline at end of file
71 </Project>
@@ -1,50 +1,50
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 Promise<T> Invoke<T>(Func<T> func) {
15 public static Promise<T> Invoke<T>(Func<T> func) {
16 var p = new Promise<T>();
16 var p = new Promise<T>();
17 var caller = TraceContext.Current;
17 var caller = TraceContext.Snapshot();
18
18
19 ThreadPool.QueueUserWorkItem(param => {
19 ThreadPool.QueueUserWorkItem(param => {
20 TraceLog.Transfer(caller);
20 TraceContext.Transfer(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 Promise<T> InvokeNewThread<T>(Func<T> func) {
31 public static Promise<T> InvokeNewThread<T>(Func<T> func) {
32 var p = new Promise<T>();
32 var p = new Promise<T>();
33
33
34 var caller = TraceContext.Current;
34 var caller = TraceContext.Snapshot();
35
35
36 var worker = new Thread(() => {
36 var worker = new Thread(() => {
37 TraceLog.Transfer(caller);
37 TraceContext.Transfer(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 }
49 }
50 }
50 }
@@ -1,97 +1,98
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.Diagnostics;
6 using System.Diagnostics;
7 using Implab.Diagnostics;
7 using Implab.Diagnostics;
8
8
9 namespace Implab.Parallels {
9 namespace Implab.Parallels {
10 public class WorkerPool : DispatchPool<Action> {
10 public class WorkerPool : DispatchPool<Action> {
11
11
12 MTQueue<Action> m_queue = new MTQueue<Action>();
12 MTQueue<Action> m_queue = new MTQueue<Action>();
13 int m_queueLength = 0;
13 int m_queueLength = 0;
14 readonly int m_threshold = 1;
14 readonly int m_threshold = 1;
15
15
16 public WorkerPool(int minThreads, int maxThreads, int threshold)
16 public WorkerPool(int minThreads, int maxThreads, int threshold)
17 : base(minThreads, maxThreads) {
17 : base(minThreads, maxThreads) {
18 m_threshold = threshold;
18 m_threshold = threshold;
19 InitPool();
19 InitPool();
20 }
20 }
21
21
22 public WorkerPool(int minThreads, int maxThreads) :
22 public WorkerPool(int minThreads, int maxThreads) :
23 base(minThreads, maxThreads) {
23 base(minThreads, maxThreads) {
24 InitPool();
24 InitPool();
25 }
25 }
26
26
27 public WorkerPool(int threads)
27 public WorkerPool(int threads)
28 : base(threads) {
28 : base(threads) {
29 InitPool();
29 InitPool();
30 }
30 }
31
31
32 public WorkerPool()
32 public WorkerPool()
33 : base() {
33 : base() {
34 InitPool();
34 InitPool();
35 }
35 }
36
36
37 public Promise<T> Invoke<T>(Func<T> task) {
37 public Promise<T> Invoke<T>(Func<T> task) {
38 if (task == null)
38 if (task == null)
39 throw new ArgumentNullException("task");
39 throw new ArgumentNullException("task");
40 if (IsDisposed)
40 if (IsDisposed)
41 throw new ObjectDisposedException(ToString());
41 throw new ObjectDisposedException(ToString());
42
42
43 var promise = new Promise<T>();
43 var promise = new Promise<T>();
44
44
45 var caller = TraceContext.Current;
45 var caller = TraceContext.Snapshot();
46
46
47 EnqueueTask(delegate() {
47 EnqueueTask(delegate() {
48 TraceLog.Transfer(caller);
48 caller.Invoke(delegate() {
49 try {
49 try {
50 promise.Resolve(task());
50 promise.Resolve(task());
51 } catch (Exception e) {
51 } catch (Exception e) {
52 promise.Reject(e);
52 promise.Reject(e);
53 }
53 }
54 });
54 });
55 });
55
56
56 return promise;
57 return promise;
57 }
58 }
58
59
59 protected void EnqueueTask(Action unit) {
60 protected void EnqueueTask(Action unit) {
60 Debug.Assert(unit != null);
61 Debug.Assert(unit != null);
61 var len = Interlocked.Increment(ref m_queueLength);
62 var len = Interlocked.Increment(ref m_queueLength);
62 m_queue.Enqueue(unit);
63 m_queue.Enqueue(unit);
63
64
64 if (len > m_threshold*ActiveThreads)
65 if (len > m_threshold*ActiveThreads)
65 GrowPool();
66 GrowPool();
66 }
67 }
67
68
68 protected override bool TryDequeue(out Action unit) {
69 protected override bool TryDequeue(out Action unit) {
69 if (m_queue.TryDequeue(out unit)) {
70 if (m_queue.TryDequeue(out unit)) {
70 Interlocked.Decrement(ref m_queueLength);
71 Interlocked.Decrement(ref m_queueLength);
71 return true;
72 return true;
72 }
73 }
73 return false;
74 return false;
74 }
75 }
75
76
76 protected override bool Suspend() {
77 protected override bool Suspend() {
77 // This override solves race condition
78 // This override solves race condition
78 // WORKER CLIENT
79 // WORKER CLIENT
79 // ---------------------------------------
80 // ---------------------------------------
80 // TryDeque == false
81 // TryDeque == false
81 // Enqueue(unit), queueLen++
82 // Enqueue(unit), queueLen++
82 // GrowPool? == NO
83 // GrowPool? == NO
83 // ActiveThreads--
84 // ActiveThreads--
84 // Suspend
85 // Suspend
85 // queueLength > 0
86 // queueLength > 0
86 // continue
87 // continue
87 if (m_queueLength > 0)
88 if (m_queueLength > 0)
88 return true;
89 return true;
89 return base.Suspend();
90 return base.Suspend();
90 }
91 }
91
92
92 protected override void InvokeUnit(Action unit) {
93 protected override void InvokeUnit(Action unit) {
93 unit();
94 unit();
94 }
95 }
95
96
96 }
97 }
97 }
98 }
General Comments 0
You need to be logged in to leave comments. Login now