##// 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 1 using System;
2 2 using System.Collections.Generic;
3 3 using System.Linq;
4 4 using System.Text;
5 5
6 6 namespace Implab.Diagnostics {
7 public class ConsoleTraceListener {
7 public class ConsoleTraceListener: TextListenerBase {
8 8
9 9 static readonly object _consoleLock = new object();
10 10
11 public void Subscribe() {
12 LogChannel<TraceEvent>.Default.Events += Default_Events;
13 }
14
15 public void Unsubscribe() {
16 LogChannel<TraceEvent>.Default.Events -= Default_Events;
17 }
11 protected override void WriteEntry(TraceContext context, EventText text) {
12 var msg = new StringBuilder();
18 13
19 void Default_Events(object sender, ValueEventArgs<TraceEvent> e) {
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++)
14 for (int i = 0; i < text.indent; i++)
26 15 msg.Append(" ");
27 msg.Append(evt.EventType);
28 msg.AppendFormat("[{0}]: ",context.ThreadId);
29 msg.Append(evt.Message);
16 msg.AppendFormat("[{0}]: {1}", context.ThreadId, text.content);
30 17
31 18 lock (_consoleLock) {
32 19 Console.ForegroundColor = (ConsoleColor)(context.ThreadId % 15 + 1);
33 20 Console.WriteLine(msg.ToString());
34 21 }
35 22 }
36 23 }
37 24 }
@@ -1,97 +1,163
1 1 using System;
2 2 using System.Collections.Generic;
3 3 using System.Linq;
4 4 using System.Text;
5 5 using System.Threading;
6 6 using System.Threading.Tasks;
7 7
8 8 namespace Implab.Diagnostics {
9 /// <summary>
10 /// ΠšΠΎΠ½Ρ‚Π΅ΠΊΡΡ‚ трассировки, привязываСтся ΠΊ ΠΏΠΎΡ‚ΠΎΠΊΡƒ ΠΈ содСрТит Π² сСбС ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎ стСкС логичСских ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ.
11 /// </summary>
12 /// <remarks>
13 /// ΠšΠΎΠ½Ρ‚Π΅ΠΊΡΡ‚ трассировки пСрСдаСтся ΡΠ»ΡƒΡˆΠ°Ρ‚Π΅Π»ΡΠΌ событий для опрСдСлСния мСста, Π³Π΄Π΅ Π²ΠΎΠ·Π½ΠΈΠΊΠ»ΠΎ событиС.
14 /// </remarks>
9 15 public class TraceContext {
10 16 LogicalOperation m_currentOperation;
11 readonly LogicalOperation m_traceBound;
17 readonly LogicalOperation m_bound;
12 18 readonly int m_threadId;
13 readonly TraceContext m_parent;
14
15 readonly static object _consoleLock = new object();
16 19
17 20 [ThreadStatic]
18 21 static TraceContext _current;
19 22
23 /// <summary>
24 /// Π’Π΅ΠΊΡƒΡ‰ΠΈΠΉ контСкст трассировки для ΠΏΠΎΡ‚ΠΎΠΊΠ°, создаСтся астоматичСски ΠΏΡ€ΠΈ ΠΏΠ΅Ρ€Π²ΠΎΠΌ ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠΈ.
25 /// </summary>
20 26 public static TraceContext Current {
21 27 get {
22 28 if (_current == null)
23 29 _current = new TraceContext();
24 30 return _current;
25 31 }
26 32 }
27 33
28 34 TraceContext(TraceContext context) {
29 35 if (context == null)
30 36 throw new ArgumentNullException("context");
31 37
32 m_parent = context;
33 38 m_currentOperation = context.CurrentOperation;
34 m_traceBound = context.CurrentOperation;
39 m_bound = context.CurrentOperation;
35 40 m_threadId = Thread.CurrentThread.ManagedThreadId;
36
37 LogEvent(TraceEventType.Transfer, "FORK {0}", context.ThreadId);
38 41 }
39 42
40 43 TraceContext() {
41 44 m_currentOperation = new LogicalOperation();
42 m_traceBound = m_currentOperation;
45 m_bound = m_currentOperation;
43 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 63 public static void Transfer(TraceContext from) {
47 _current = from == null ? new TraceContext() : new TraceContext(from);
48 }
49
50 public TraceContext ParentContext {
51 get {
52 return m_parent;
64 if (_current == from)
65 return;
66 if (from != null) {
67 var context = new TraceContext(from);
68 context.LogEvent(TraceEventType.Transfer, "[{0}]-->[{1}]",from.ThreadId, context.ThreadId);
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 102 public LogicalOperation CurrentOperation {
57 103 get {
58 104 return m_currentOperation;
59 105 }
60 106 }
61 107
62 public LogicalOperation TraceBound {
108 /// <summary>
109 /// ΠžΠΏΠ΅Ρ€Π°Ρ†ΠΈΡ Π½ΠΈΠΆΠ΅ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ нСльзя ΠΎΠΏΡƒΡΠΊΠ°Ρ‚ΡŒΡΡ Π² стСкС логичСских ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ, Ρ‚.Π΅. ΠΎΠ½Π° Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½Π° Π² Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌ контСкстС.
110 /// </summary>
111 public LogicalOperation BoundOperation {
63 112 get {
64 return m_traceBound;
113 return m_bound;
65 114 }
66 115 }
67 116
117 /// <summary>
118 /// ΠŸΠΎΡ‚ΠΎΠΊ, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ создан контСкст трассировки.
119 /// </summary>
68 120 public int ThreadId {
69 121 get {
70 122 return m_threadId;
71 123 }
72 124 }
73 125
126 /// <summary>
127 /// НачинаСт Π±Π΅Π·Ρ‹ΠΌΡΠ½Π½ΡƒΡŽ Π»ΠΎΠ³ΠΈΡ‡Π΅ΡΠΊΡƒΡŽ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ.
128 /// </summary>
74 129 public void StartLogicalOperation() {
75 130 StartLogicalOperation(null);
76 131 }
77 132
133 /// <summary>
134 /// НачинаСт Π»ΠΎΠ³ΠΈΡ‡Π΅ΡΠΊΡƒΡŽ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ с ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹ΠΌ ΠΈΠΌΠ΅Π½Π΅ΠΌ. Бозданная опСрация Π±ΡƒΠ΄Π΅Ρ‚ Π΄ΠΎΠ±Π²Π°Π»Π΅Π½Π° Π² стСк логичСских ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ контСкста, Π·Π°Ρ‚Π΅ΠΌ Π±ΡƒΠ΄Π΅Ρ‚ создано ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΠ²ΡƒΡŽΡ‰Π΅Π΅ событиС.
135 /// </summary>
136 /// <param name="name">Имя Π½Π°Ρ‡ΠΈΠ½Π°Π΅ΠΌΠΎΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</param>
78 137 public void StartLogicalOperation(string name) {
79 LogEvent(TraceEventType.OperationStarted, "{0}", name);
80 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 149 public void EndLogicalOperation() {
84 if (m_traceBound == m_currentOperation) {
150 if (m_bound == m_currentOperation) {
85 151 LogEvent(TraceEventType.Error, "Trying to end the operation which isn't belongs to current trace");
86 152 } else {
87 153 var op = m_currentOperation;
154 LogEvent(TraceEventType.OperationCompleted, "{0} {1} ms", op.Name, op.Duration);
88 155 m_currentOperation = m_currentOperation.Parent;
89 LogEvent(TraceEventType.OperationCompleted, "{0} {1} ms", op.Name, op.Duration);
90 156 }
91 157 }
92 158
93 159 void LogEvent(TraceEventType type, string format, params object[] args) {
94 160 LogChannel<TraceEvent>.Default.LogEvent(this, TraceEvent.Create(type, format, args));
95 161 }
96 162 }
97 163 }
@@ -1,27 +1,31
1 1 using System;
2 2 using System.Collections.Generic;
3 3 using System.Linq;
4 4 using System.Text;
5 5
6 6 namespace Implab.Diagnostics {
7 7 public class TraceEvent {
8 8 public string Message {
9 9 get;
10 10 private set;
11 11 }
12 12
13 13 public TraceEventType EventType {
14 14 get;
15 15 private set;
16 16 }
17 17
18 18 public TraceEvent(TraceEventType type, string message) {
19 19 EventType = type;
20 20 Message = message;
21 21 }
22 22
23 public override string ToString() {
24 return String.Format("{0}: {1}", EventType, Message);
25 }
26
23 27 public static TraceEvent Create(TraceEventType type, string format, params object[] args) {
24 28 return new TraceEvent(type, String.Format(format, args));
25 29 }
26 30 }
27 31 }
@@ -1,53 +1,50
1 1 using System;
2 2 using System.Collections.Generic;
3 3 using System.Diagnostics;
4 4 using System.Linq;
5 5 using System.Text;
6 6 using System.Threading.Tasks;
7 7
8 8 namespace Implab.Diagnostics {
9 9 /// <summary>
10 /// Класс для ΠΏΡƒΠ±Π»ΠΈΠΊΠ°Ρ†ΠΈΠΈ событий выполнСния ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹, события ΠΏΡƒΠ±Π»ΠΈΠΊΡƒΡŽΡ‚ΡΡ Ρ‡Π΅Ρ€Π΅Π· <see cref="LogChannel{TraceEvent}"/>
10 /// Класс для ΠΏΡƒΠ±Π»ΠΈΠΊΠ°Ρ†ΠΈΠΈ событий выполнСния ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹, события ΠΏΡƒΠ±Π»ΠΈΠΊΡƒΡŽΡ‚ΡΡ Ρ‡Π΅Ρ€Π΅Π· <see cref="LogChannel{TraceEvent}"/>.
11 /// Π–ΡƒΡ€Π½Π°Π» трассировки ΠΎΡ‚Ρ€Π°ΠΆΠ°Π΅Ρ‚ логичСский Ρ…ΠΎΠ΄ выполнСния ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ ΠΈ сущСствуСт всСгда, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ тСсно связан с
12 /// контСкстом трассировки.
11 13 /// </summary>
12 14 public static class TraceLog {
13 15 [Conditional("TRACE")]
14 public static void Transfer(TraceContext from) {
15 TraceContext.Transfer(from);
16 }
17
18 [Conditional("TRACE")]
19 16 public static void StartLogicalOperation() {
20 17 TraceContext.Current.StartLogicalOperation();
21 18 }
22 19
23 20 [Conditional("TRACE")]
24 21 public static void StartLogicalOperation(string name) {
25 22 TraceContext.Current.StartLogicalOperation(name);
26 23 }
27 24
28 25 [Conditional("TRACE")]
29 26 public static void EndLogicalOperation() {
30 27 TraceContext.Current.EndLogicalOperation();
31 28 }
32 29
33 30 [Conditional("TRACE")]
34 31 public static void TraceInformation(string format, params object[] arguments) {
35 32 LogChannel<TraceEvent>.Default.LogEvent(TraceEvent.Create(TraceEventType.Information, format, arguments));
36 33 }
37 34
38 35 [Conditional("TRACE")]
39 36 public static void TraceWarning(string format, params object[] arguments) {
40 37 LogChannel<TraceEvent>.Default.LogEvent(TraceEvent.Create(TraceEventType.Warning, format, arguments));
41 38 }
42 39
43 40 [Conditional("TRACE")]
44 41 public static void TraceError(string format, params object[] arguments) {
45 42 LogChannel<TraceEvent>.Default.LogEvent(TraceEvent.Create(TraceEventType.Error, format, arguments));
46 43 }
47 44
48 45 [Conditional("TRACE")]
49 46 public static void TraceError(Exception err) {
50 47 TraceError("{0}", err);
51 48 }
52 49 }
53 50 }
@@ -1,63 +1,71
1 1 ο»Ώ<?xml version="1.0" encoding="utf-8"?>
2 2 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3 3 <PropertyGroup>
4 4 <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
5 5 <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
6 6 <ProductVersion>10.0.0</ProductVersion>
7 7 <SchemaVersion>2.0</SchemaVersion>
8 8 <ProjectGuid>{F550F1F8-8746-4AD0-9614-855F4C4B7F05}</ProjectGuid>
9 9 <OutputType>Library</OutputType>
10 10 <RootNamespace>Implab</RootNamespace>
11 11 <AssemblyName>Implab</AssemblyName>
12 12 </PropertyGroup>
13 13 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
14 14 <DebugSymbols>true</DebugSymbols>
15 15 <DebugType>full</DebugType>
16 16 <Optimize>false</Optimize>
17 17 <OutputPath>bin\Debug</OutputPath>
18 18 <DefineConstants>TRACE;DEBUG;</DefineConstants>
19 19 <ErrorReport>prompt</ErrorReport>
20 20 <WarningLevel>4</WarningLevel>
21 21 <ConsolePause>false</ConsolePause>
22 22 </PropertyGroup>
23 23 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
24 24 <DebugType>full</DebugType>
25 25 <Optimize>true</Optimize>
26 26 <OutputPath>bin\Release</OutputPath>
27 27 <ErrorReport>prompt</ErrorReport>
28 28 <WarningLevel>4</WarningLevel>
29 29 <ConsolePause>false</ConsolePause>
30 30 </PropertyGroup>
31 31 <ItemGroup>
32 32 <Reference Include="System" />
33 33 </ItemGroup>
34 34 <ItemGroup>
35 <Compile Include="Component.cs" />
35 36 <Compile Include="Diagnostics\ConsoleTraceListener.cs" />
37 <Compile Include="Diagnostics\EventText.cs" />
38 <Compile Include="Diagnostics\IEventTextFormatter.cs" />
36 39 <Compile Include="Diagnostics\LogChannel.cs" />
37 40 <Compile Include="Diagnostics\LogicalOperation.cs" />
41 <Compile Include="Diagnostics\TextFileListener.cs" />
42 <Compile Include="Diagnostics\TextListenerBase.cs" />
38 43 <Compile Include="Diagnostics\TraceLog.cs" />
39 44 <Compile Include="Diagnostics\TraceContext.cs" />
40 45 <Compile Include="Diagnostics\TraceEvent.cs" />
41 46 <Compile Include="Diagnostics\TraceEventType.cs" />
47 <Compile Include="Disposable.cs" />
42 48 <Compile Include="ICancellable.cs" />
43 49 <Compile Include="IProgressHandler.cs" />
44 50 <Compile Include="IProgressNotifier.cs" />
45 51 <Compile Include="IPromise.cs" />
46 52 <Compile Include="IPromiseBase.cs" />
53 <Compile Include="IServiceLocator.cs" />
47 54 <Compile Include="ITaskController.cs" />
48 55 <Compile Include="ManagedPromise.cs" />
49 56 <Compile Include="Parallels\DispatchPool.cs" />
50 57 <Compile Include="Parallels\ArrayTraits.cs" />
51 58 <Compile Include="Parallels\MTQueue.cs" />
52 59 <Compile Include="Parallels\WorkerPool.cs" />
60 <Compile Include="ServiceLocator.cs" />
53 61 <Compile Include="TaskController.cs" />
54 62 <Compile Include="ProgressInitEventArgs.cs" />
55 63 <Compile Include="Properties\AssemblyInfo.cs" />
56 64 <Compile Include="Promise.cs" />
57 65 <Compile Include="Parallels\AsyncPool.cs" />
58 66 <Compile Include="Safe.cs" />
59 67 <Compile Include="ValueEventArgs.cs" />
60 68 </ItemGroup>
61 69 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
62 70 <ItemGroup />
63 71 </Project> No newline at end of file
@@ -1,50 +1,50
1 1 using Implab.Diagnostics;
2 2 using System;
3 3 using System.Threading;
4 4
5 5 namespace Implab.Parallels {
6 6 /// <summary>
7 7 /// Класс для распаралСливания Π·Π°Π΄Π°Ρ‡.
8 8 /// </summary>
9 9 /// <remarks>
10 10 /// Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ Π΄Π°Π½Π½Ρ‹ΠΉ класс ΠΈ лямда выраТСния ΠΌΠΎΠΆΠ½ΠΎ Ρ€Π°ΡΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΠΈΡ‚ΡŒ
11 11 /// вычислСния, для этого ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ концСпция ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ.
12 12 /// </remarks>
13 13 public static class AsyncPool {
14 14
15 15 public static Promise<T> Invoke<T>(Func<T> func) {
16 16 var p = new Promise<T>();
17 var caller = TraceContext.Current;
17 var caller = TraceContext.Snapshot();
18 18
19 19 ThreadPool.QueueUserWorkItem(param => {
20 TraceLog.Transfer(caller);
20 TraceContext.Transfer(caller);
21 21 try {
22 22 p.Resolve(func());
23 23 } catch(Exception e) {
24 24 p.Reject(e);
25 25 }
26 26 });
27 27
28 28 return p;
29 29 }
30 30
31 31 public static Promise<T> InvokeNewThread<T>(Func<T> func) {
32 32 var p = new Promise<T>();
33 33
34 var caller = TraceContext.Current;
34 var caller = TraceContext.Snapshot();
35 35
36 36 var worker = new Thread(() => {
37 TraceLog.Transfer(caller);
37 TraceContext.Transfer(caller);
38 38 try {
39 39 p.Resolve(func());
40 40 } catch (Exception e) {
41 41 p.Reject(e);
42 42 }
43 43 });
44 44 worker.IsBackground = true;
45 45 worker.Start();
46 46
47 47 return p;
48 48 }
49 49 }
50 50 }
@@ -1,97 +1,98
1 1 using System;
2 2 using System.Collections.Generic;
3 3 using System.Linq;
4 4 using System.Text;
5 5 using System.Threading;
6 6 using System.Diagnostics;
7 7 using Implab.Diagnostics;
8 8
9 9 namespace Implab.Parallels {
10 10 public class WorkerPool : DispatchPool<Action> {
11 11
12 12 MTQueue<Action> m_queue = new MTQueue<Action>();
13 13 int m_queueLength = 0;
14 14 readonly int m_threshold = 1;
15 15
16 16 public WorkerPool(int minThreads, int maxThreads, int threshold)
17 17 : base(minThreads, maxThreads) {
18 18 m_threshold = threshold;
19 19 InitPool();
20 20 }
21 21
22 22 public WorkerPool(int minThreads, int maxThreads) :
23 23 base(minThreads, maxThreads) {
24 24 InitPool();
25 25 }
26 26
27 27 public WorkerPool(int threads)
28 28 : base(threads) {
29 29 InitPool();
30 30 }
31 31
32 32 public WorkerPool()
33 33 : base() {
34 34 InitPool();
35 35 }
36 36
37 37 public Promise<T> Invoke<T>(Func<T> task) {
38 38 if (task == null)
39 39 throw new ArgumentNullException("task");
40 40 if (IsDisposed)
41 41 throw new ObjectDisposedException(ToString());
42 42
43 43 var promise = new Promise<T>();
44 44
45 var caller = TraceContext.Current;
45 var caller = TraceContext.Snapshot();
46 46
47 47 EnqueueTask(delegate() {
48 TraceLog.Transfer(caller);
49 try {
50 promise.Resolve(task());
51 } catch (Exception e) {
52 promise.Reject(e);
53 }
48 caller.Invoke(delegate() {
49 try {
50 promise.Resolve(task());
51 } catch (Exception e) {
52 promise.Reject(e);
53 }
54 });
54 55 });
55 56
56 57 return promise;
57 58 }
58 59
59 60 protected void EnqueueTask(Action unit) {
60 61 Debug.Assert(unit != null);
61 62 var len = Interlocked.Increment(ref m_queueLength);
62 63 m_queue.Enqueue(unit);
63 64
64 65 if (len > m_threshold*ActiveThreads)
65 66 GrowPool();
66 67 }
67 68
68 69 protected override bool TryDequeue(out Action unit) {
69 70 if (m_queue.TryDequeue(out unit)) {
70 71 Interlocked.Decrement(ref m_queueLength);
71 72 return true;
72 73 }
73 74 return false;
74 75 }
75 76
76 77 protected override bool Suspend() {
77 78 // This override solves race condition
78 79 // WORKER CLIENT
79 80 // ---------------------------------------
80 81 // TryDeque == false
81 82 // Enqueue(unit), queueLen++
82 83 // GrowPool? == NO
83 84 // ActiveThreads--
84 85 // Suspend
85 86 // queueLength > 0
86 87 // continue
87 88 if (m_queueLength > 0)
88 89 return true;
89 90 return base.Suspend();
90 91 }
91 92
92 93 protected override void InvokeUnit(Action unit) {
93 94 unit();
94 95 }
95 96
96 97 }
97 98 }
General Comments 0
You need to be logged in to leave comments. Login now