##// END OF EJS Templates
working on diagnostics
cin -
r285:b6924f444abd v3
parent child
Show More
@@ -0,0 +1,22
1 using System.Diagnostics;
2
3 namespace Implab.Diagnostics
4 {
5 public class ChannelInfo
6 {
7 internal ChannelInfo(object id, TraceSource source) {
8 Debug.Assert(id != null);
9 Debug.Assert(source != null);
10
11 Id = id;
12 Source = source;
13
14 }
15
16 public object Id { get; private set; }
17
18 public TraceSource Source { get; private set; }
19
20
21 }
22 } No newline at end of file
@@ -0,0 +1,76
1 using System;
2 using System.Collections.Generic;
3 using System.Diagnostics;
4 using Implab.Parallels;
5
6 namespace Implab.Diagnostics {
7 public class TraceChannelRegistry {
8
9 class Subscription : IDisposable {
10 readonly Action<object> m_unsubscribe;
11
12 public Subscription(Action<object> unsubscribe) {
13 m_unsubscribe = unsubscribe;
14 }
15
16 public void Dispose() {
17 m_unsubscribe(this);
18 }
19 }
20
21 public static TraceChannelRegistry AllCannels { get; } = new TraceChannelRegistry();
22
23 readonly object m_lock = new object();
24
25 readonly Dictionary<object, Action<ChannelInfo>> m_subscriptions = new Dictionary<object, Action<ChannelInfo>>();
26 readonly SimpleAsyncQueue<ChannelInfo> m_channels = new SimpleAsyncQueue<ChannelInfo>();
27
28 internal void NotifyChannelCreated(ChannelInfo channel) {
29 // notifications can run in parallel
30 Action<ChannelInfo>[] handlers = null;
31
32 lock(m_lock) {
33 m_channels.Enqueue(channel);
34 if (m_subscriptions.Count > 0) {
35 handlers = new Action<ChannelInfo>[m_subscriptions.Count];
36 m_subscriptions.Values.CopyTo(handlers, 0);
37 }
38 }
39
40 if (handlers != null)
41 foreach(var h in handlers)
42 h(channel);
43 }
44
45 /// <summary>
46 /// Subscribes the specified handler to notifications about new trace
47 /// channels
48 /// </summary>
49 /// <param name="handler"></param>
50 /// <returns></returns>
51 public IDisposable Subscribe(Action<ChannelInfo> handler, bool existing) {
52 Safe.ArgumentNotNull(handler, nameof(handler));
53
54 var cookie = new Subscription(RemoveSubscription);
55
56 IEnumerable<ChannelInfo> snap;
57
58 lock(m_lock) {
59 m_subscriptions.Add(cookie, handler);
60 snap = m_channels.Snapshot();
61 }
62
63 if (existing) {
64 foreach(var c in snap)
65 handler(c);
66 }
67
68 return cookie;
69 }
70
71 void RemoveSubscription(object cookie) {
72 lock(m_lock)
73 m_subscriptions.Remove(cookie);
74 }
75 }
76 } No newline at end of file
@@ -1,191 +1,191
1 using Xunit;
1 using Xunit;
2 using System;
2 using System;
3 using Implab.Automaton;
3 using Implab.Automaton;
4 using Implab.Xml;
4 using Implab.Xml;
5 using System.Xml;
5 using System.Xml;
6 using Implab.Formats;
6 using Implab.Formats;
7 using Implab.Formats.Json;
7 using Implab.Formats.Json;
8 using System.IO;
8 using System.IO;
9 using Implab.Test.Model;
9 using Implab.Test.Model;
10
10
11 namespace Implab.Test {
11 namespace Implab.Test {
12 public class JsonTests {
12 public class JsonTests {
13
13
14 [Fact]
14 [Fact]
15 public void TestScannerValidTokens() {
15 public void TestScannerValidTokens() {
16 using (var scanner = JsonStringScanner.Create(@"9123, -123, 0, 0.1, -0.2, -0.1e3, 1.3E-3, ""some \t\n\u0020 text"", literal []{}:")) {
16 using (var scanner = JsonStringScanner.Create(@"9123, -123, 0, 0.1, -0.2, -0.1e3, 1.3E-3, ""some \t\n\u0020 text"", literal []{}:")) {
17
17
18 Tuple<JsonTokenType, object>[] expexted = {
18 Tuple<JsonTokenType, object>[] expexted = {
19 new Tuple<JsonTokenType,object>(JsonTokenType.Number, "9123"),
19 new Tuple<JsonTokenType,object>(JsonTokenType.Number, "9123"),
20 new Tuple<JsonTokenType,object>(JsonTokenType.ValueSeparator, null),
20 new Tuple<JsonTokenType,object>(JsonTokenType.ValueSeparator, null),
21 new Tuple<JsonTokenType,object>(JsonTokenType.Number, "-123"),
21 new Tuple<JsonTokenType,object>(JsonTokenType.Number, "-123"),
22 new Tuple<JsonTokenType,object>(JsonTokenType.ValueSeparator, null),
22 new Tuple<JsonTokenType,object>(JsonTokenType.ValueSeparator, null),
23 new Tuple<JsonTokenType,object>(JsonTokenType.Number, "0"),
23 new Tuple<JsonTokenType,object>(JsonTokenType.Number, "0"),
24 new Tuple<JsonTokenType,object>(JsonTokenType.ValueSeparator, null),
24 new Tuple<JsonTokenType,object>(JsonTokenType.ValueSeparator, null),
25 new Tuple<JsonTokenType,object>(JsonTokenType.Number, "0.1"),
25 new Tuple<JsonTokenType,object>(JsonTokenType.Number, "0.1"),
26 new Tuple<JsonTokenType,object>(JsonTokenType.ValueSeparator, null),
26 new Tuple<JsonTokenType,object>(JsonTokenType.ValueSeparator, null),
27 new Tuple<JsonTokenType,object>(JsonTokenType.Number, "-0.2"),
27 new Tuple<JsonTokenType,object>(JsonTokenType.Number, "-0.2"),
28 new Tuple<JsonTokenType,object>(JsonTokenType.ValueSeparator, null),
28 new Tuple<JsonTokenType,object>(JsonTokenType.ValueSeparator, null),
29 new Tuple<JsonTokenType,object>(JsonTokenType.Number, "-0.1e3"),
29 new Tuple<JsonTokenType,object>(JsonTokenType.Number, "-0.1e3"),
30 new Tuple<JsonTokenType,object>(JsonTokenType.ValueSeparator, null),
30 new Tuple<JsonTokenType,object>(JsonTokenType.ValueSeparator, null),
31 new Tuple<JsonTokenType,object>(JsonTokenType.Number, "1.3E-3"),
31 new Tuple<JsonTokenType,object>(JsonTokenType.Number, "1.3E-3"),
32 new Tuple<JsonTokenType,object>(JsonTokenType.ValueSeparator, null),
32 new Tuple<JsonTokenType,object>(JsonTokenType.ValueSeparator, null),
33 new Tuple<JsonTokenType,object>(JsonTokenType.String, "some \t\n text"),
33 new Tuple<JsonTokenType,object>(JsonTokenType.String, "some \t\n text"),
34 new Tuple<JsonTokenType,object>(JsonTokenType.ValueSeparator, null),
34 new Tuple<JsonTokenType,object>(JsonTokenType.ValueSeparator, null),
35 new Tuple<JsonTokenType,object>(JsonTokenType.Literal, "literal"),
35 new Tuple<JsonTokenType,object>(JsonTokenType.Literal, "literal"),
36 new Tuple<JsonTokenType,object>(JsonTokenType.BeginArray, null),
36 new Tuple<JsonTokenType,object>(JsonTokenType.BeginArray, null),
37 new Tuple<JsonTokenType,object>(JsonTokenType.EndArray, null),
37 new Tuple<JsonTokenType,object>(JsonTokenType.EndArray, null),
38 new Tuple<JsonTokenType,object>(JsonTokenType.BeginObject, null),
38 new Tuple<JsonTokenType,object>(JsonTokenType.BeginObject, null),
39 new Tuple<JsonTokenType,object>(JsonTokenType.EndObject, null),
39 new Tuple<JsonTokenType,object>(JsonTokenType.EndObject, null),
40 new Tuple<JsonTokenType,object>(JsonTokenType.NameSeparator, null)
40 new Tuple<JsonTokenType,object>(JsonTokenType.NameSeparator, null)
41 };
41 };
42
42
43 string value;
43 string value;
44 JsonTokenType tokenType;
44 JsonTokenType tokenType;
45 for (var i = 0; i < expexted.Length; i++) {
45 for (var i = 0; i < expexted.Length; i++) {
46
46
47 Assert.True(scanner.ReadToken(out value, out tokenType));
47 Assert.True(scanner.ReadToken(out value, out tokenType));
48 Assert.Equal(expexted[i].Item1, tokenType);
48 Assert.Equal(expexted[i].Item1, tokenType);
49 Assert.Equal(expexted[i].Item2, value);
49 Assert.Equal(expexted[i].Item2, value);
50 }
50 }
51
51
52 Assert.False(scanner.ReadToken(out value, out tokenType));
52 Assert.False(scanner.ReadToken(out value, out tokenType));
53 }
53 }
54 }
54 }
55
55
56 [Fact]
56 [Fact]
57 public void TestScannerBadTokens() {
57 public void TestScannerBadTokens() {
58 var bad = new[] {
58 var bad = new[] {
59 " 1",
59 " 1",
60 " literal",
60 " literal",
61 " \"",
61 " \"",
62 "\"unclosed string",
62 "\"unclosed string",
63 "1.bad",
63 "1.bad",
64 "001", // should be read as three numbers
64 "001", // should be read as three numbers
65 "--10",
65 "--10",
66 "+10",
66 "+10",
67 "1.0.0",
67 "1.0.0",
68 "1e1.0",
68 "1e1.0",
69 "l1teral0",
69 "l1teral0",
70 ".123",
70 ".123",
71 "-.123"
71 "-.123"
72 };
72 };
73
73
74 foreach (var json in bad) {
74 foreach (var json in bad) {
75 using (var scanner = JsonStringScanner.Create(json)) {
75 using (var scanner = JsonStringScanner.Create(json)) {
76 try {
76 try {
77 string value;
77 string value;
78 JsonTokenType token;
78 JsonTokenType token;
79 scanner.ReadToken(out value, out token);
79 scanner.ReadToken(out value, out token);
80 if (!Object.Equals(value, json)) {
80 if (!Object.Equals(value, json)) {
81 Console.WriteLine("'{0}' is read as {1}", json, value is String ? String.Format("'{0}'", value) : value);
81 Console.WriteLine("'{0}' is read as {1}", json, value is String ? String.Format("'{0}'", value) : value);
82 continue;
82 continue;
83 }
83 }
84 Assert.True(false, $"Token '{json}' shouldn't pass");
84 Assert.True(false, $"Token '{json}' shouldn't pass");
85 } catch (ParserException e) {
85 } catch (ParserException e) {
86 Console.WriteLine(e.Message);
86 Console.WriteLine(e.Message);
87 }
87 }
88 }
88 }
89 }
89 }
90 }
90 }
91
91
92 [Fact]
92 [Fact]
93 public void JsonXmlReaderSimpleTest() {
93 public void JsonXmlReaderSimpleTest() {
94 var json = "\"some text\"";
94 //var json = "\"some text\"";
95 //Console.WriteLine($"JSON: {json}");
95 //Console.WriteLine($"JSON: {json}");
96 //Console.WriteLine("XML");
96 //Console.WriteLine("XML");
97 /*using (var xmlReader = new JsonXmlReader(new JSONParser(json), new JsonXmlReaderOptions { NamespaceUri = "JsonXmlReaderSimpleTest", RootName = "string", NodesPrefix = "json" })) {
97 /*using (var xmlReader = new JsonXmlReader(new JSONParser(json), new JsonXmlReaderOptions { NamespaceUri = "JsonXmlReaderSimpleTest", RootName = "string", NodesPrefix = "json" })) {
98 Assert.AreEqual(xmlReader.ReadState, System.Xml.ReadState.Initial);
98 Assert.AreEqual(xmlReader.ReadState, System.Xml.ReadState.Initial);
99
99
100 AssertRead(xmlReader, XmlNodeType.XmlDeclaration);
100 AssertRead(xmlReader, XmlNodeType.XmlDeclaration);
101 AssertRead(xmlReader, XmlNodeType.Element);
101 AssertRead(xmlReader, XmlNodeType.Element);
102 AssertRead(xmlReader, XmlNodeType.Text);
102 AssertRead(xmlReader, XmlNodeType.Text);
103 AssertRead(xmlReader, XmlNodeType.EndElement);
103 AssertRead(xmlReader, XmlNodeType.EndElement);
104 Assert.IsFalse(xmlReader.Read());
104 Assert.IsFalse(xmlReader.Read());
105 }*/
105 }*/
106
106
107 DumpJsonParse("\"text value\"");
107 DumpJsonParse("\"text value\"");
108 DumpJsonParse("null");
108 DumpJsonParse("null");
109 DumpJsonParse("true");
109 DumpJsonParse("true");
110 DumpJsonParse("{}");
110 DumpJsonParse("{}");
111 DumpJsonParse("[]");
111 DumpJsonParse("[]");
112 DumpJsonParse("{\"one\":1, \"two\":2}");
112 DumpJsonParse("{\"one\":1, \"two\":2}");
113 DumpJsonParse("[1,\"\",2,3]");
113 DumpJsonParse("[1,\"\",2,3]");
114 DumpJsonParse("[{\"info\": [7,8,9]}]");
114 DumpJsonParse("[{\"info\": [7,8,9]}]");
115 DumpJsonFlatParse("[1,2,\"\",[3,4],{\"info\": [5,6]},{\"num\": [7,8,null]}, null,[null]]");
115 DumpJsonFlatParse("[1,2,\"\",[3,4],{\"info\": [5,6]},{\"num\": [7,8,null]}, null,[null]]");
116 }
116 }
117
117
118 [Fact]
118 [Fact]
119 public void XmlToJsonTransform() {
119 public void XmlToJsonTransform() {
120 var person = new Person {
120 var person = new Person {
121 FirstName = "Charlie",
121 FirstName = "Charlie",
122 LastName = "Brown",
122 LastName = "Brown",
123 Age = 19,
123 Age = 19,
124 AgeSpecified = true
124 AgeSpecified = true
125 };
125 };
126
126
127 var doc = SerializationHelpers.SerializeAsXmlDocument(person);
127 var doc = SerializationHelpers.SerializeAsXmlDocument(person);
128
128
129 using (var writer = new StringWriter()) {
129 using (var writer = new StringWriter()) {
130 XmlToJson.Default.Transform(doc,null, writer);
130 XmlToJson.Default.Transform(doc,null, writer);
131 Console.WriteLine(writer.ToString());
131 Console.WriteLine(writer.ToString());
132 }
132 }
133 }
133 }
134
134
135 [Fact]
135 [Fact]
136 public void JsonSerialization() {
136 public void JsonSerialization() {
137 var person = new Person {
137 var person = new Person {
138 FirstName = "Charlie",
138 FirstName = "Charlie",
139 LastName = "Brown",
139 LastName = "Brown",
140 Age = 19,
140 Age = 19,
141 AgeSpecified = true,
141 AgeSpecified = true,
142 Tags = new [] { "brave", "stupid" }
142 Tags = new [] { "brave", "stupid" }
143 };
143 };
144
144
145 var data = SerializationHelpers.SerializeJsonAsString(person);
145 var data = SerializationHelpers.SerializeJsonAsString(person);
146 Console.WriteLine(data);
146 Console.WriteLine(data);
147 var clone = SerializationHelpers.DeserializeJsonFromString<Person>(data);
147 var clone = SerializationHelpers.DeserializeJsonFromString<Person>(data);
148
148
149 Assert.Equal(person.FirstName, clone.FirstName);
149 Assert.Equal(person.FirstName, clone.FirstName);
150 Assert.Equal(person.LastName, clone.LastName);
150 Assert.Equal(person.LastName, clone.LastName);
151 Assert.Equal(person.Age, clone.Age);
151 Assert.Equal(person.Age, clone.Age);
152 Assert.Equal(person.AgeSpecified, clone.AgeSpecified);
152 Assert.Equal(person.AgeSpecified, clone.AgeSpecified);
153 Assert.Equal(person.Tags, person.Tags);
153 Assert.Equal(person.Tags, person.Tags);
154 }
154 }
155
155
156 void AssertRead(XmlReader reader, XmlNodeType expected) {
156 void AssertRead(XmlReader reader, XmlNodeType expected) {
157 Assert.True(reader.Read());
157 Assert.True(reader.Read());
158 Console.WriteLine($"{new string(' ', reader.Depth * 2)}{reader}");
158 Console.WriteLine($"{new string(' ', reader.Depth * 2)}{reader}");
159 Assert.Equal(expected, reader.NodeType);
159 Assert.Equal(expected, reader.NodeType);
160 }
160 }
161
161
162 void DumpJsonParse(string json) {
162 void DumpJsonParse(string json) {
163 Console.WriteLine($"JSON: {json}");
163 Console.WriteLine($"JSON: {json}");
164 Console.WriteLine("XML");
164 Console.WriteLine("XML");
165 using (var xmlWriter = XmlWriter.Create(Console.Out, new XmlWriterSettings {
165 using (var xmlWriter = XmlWriter.Create(Console.Out, new XmlWriterSettings {
166 Indent = true,
166 Indent = true,
167 CloseOutput = false,
167 CloseOutput = false,
168 ConformanceLevel = ConformanceLevel.Document
168 ConformanceLevel = ConformanceLevel.Document
169 }))
169 }))
170 using (var xmlReader = new JsonXmlReader(JsonReader.ParseString(json), new JsonXmlReaderOptions { NamespaceUri = "JsonXmlReaderSimpleTest", RootName = "Data", NodesPrefix = "json", CaseTransform = JsonXmlCaseTransform.UcFirst, ArrayItemName = "Item" })) {
170 using (var xmlReader = new JsonXmlReader(JsonReader.ParseString(json), new JsonXmlReaderOptions { NamespaceUri = "JsonXmlReaderSimpleTest", RootName = "Data", NodesPrefix = "json", CaseTransform = JsonXmlCaseTransform.UcFirst, ArrayItemName = "Item" })) {
171 xmlWriter.WriteNode(xmlReader, false);
171 xmlWriter.WriteNode(xmlReader, false);
172 }
172 }
173 Console.WriteLine();
173 Console.WriteLine();
174 }
174 }
175
175
176 void DumpJsonFlatParse(string json) {
176 void DumpJsonFlatParse(string json) {
177 Console.WriteLine($"JSON: {json}");
177 Console.WriteLine($"JSON: {json}");
178 Console.WriteLine("XML");
178 Console.WriteLine("XML");
179 using (var xmlWriter = XmlWriter.Create(Console.Out, new XmlWriterSettings {
179 using (var xmlWriter = XmlWriter.Create(Console.Out, new XmlWriterSettings {
180 Indent = true,
180 Indent = true,
181 CloseOutput = false,
181 CloseOutput = false,
182 ConformanceLevel = ConformanceLevel.Document
182 ConformanceLevel = ConformanceLevel.Document
183 }))
183 }))
184 using (var xmlReader = new JsonXmlReader(JsonReader.ParseString(json), new JsonXmlReaderOptions { NamespaceUri = "JsonXmlReaderSimpleTest", NodesPrefix = "", FlattenArrays = true })) {
184 using (var xmlReader = new JsonXmlReader(JsonReader.ParseString(json), new JsonXmlReaderOptions { NamespaceUri = "JsonXmlReaderSimpleTest", NodesPrefix = "", FlattenArrays = true })) {
185 xmlWriter.WriteNode(xmlReader, false);
185 xmlWriter.WriteNode(xmlReader, false);
186 }
186 }
187 Console.WriteLine();
187 Console.WriteLine();
188 }
188 }
189 }
189 }
190 }
190 }
191
191
@@ -1,161 +1,160
1 // enable System.Diagnostics trace methods
1 // enable System.Diagnostics trace methods
2 #define TRACE
2 #define TRACE
3
3
4 using System;
4 using System;
5 using System.Collections.Generic;
5 using System.Collections.Generic;
6 using System.Diagnostics;
6 using System.Diagnostics;
7 using System.Linq;
7 using System.Linq;
8 using System.Text;
8 using System.Text;
9 using System.Threading;
9 using System.Threading;
10 using System.Threading.Tasks;
10 using System.Threading.Tasks;
11
11
12 namespace Implab.Diagnostics {
12 namespace Implab.Diagnostics {
13 public static class Trace<T> {
13 public static class Trace<T> {
14
14
15 static Lazy<TraceSource> _traceSource = new Lazy<TraceSource>(CreateChannel, LazyThreadSafetyMode.ExecutionAndPublication);
15 static Lazy<TraceSource> _traceSource = new Lazy<TraceSource>(CreateChannel, LazyThreadSafetyMode.ExecutionAndPublication);
16
16
17 static int _nextId;
17 static int _nextId;
18
18
19 static TraceSource CreateChannel() {
19 static TraceSource CreateChannel() {
20 var id = Interlocked.Increment(ref _nextId);
20 var id = Interlocked.Increment(ref _nextId);
21 return new TraceSource(typeof(T).Name);
21 var trs = new TraceSource(typeof(T).Name);
22
23 TraceChannelRegistry.AllCannels.NotifyChannelCreated(new ChannelInfo(typeof(T), trs));
24
25 return trs;
22 }
26 }
23
27
24 public static TraceSource TraceSource { get { return _traceSource.Value; } }
28 public static TraceSource TraceSource { get { return _traceSource.Value; } }
25
29
26 public static IDisposable Subscribe() {
27
28 throw new NotImplementedException();
29 }
30
31 #if NETFX_TRACE_BUG
30 #if NETFX_TRACE_BUG
32 readonly static AsyncLocal<object> m_currentOperation = new AsyncLocal<object>();
31 readonly static AsyncLocal<object> m_currentOperation = new AsyncLocal<object>();
33 #endif
32 #endif
34
33
35 /// <summary>
34 /// <summary>
36 /// Starts the logical operation nested to the current operation nested to the current one.
35 /// Starts the logical operation nested to the current operation nested to the current one.
37 /// </summary>
36 /// </summary>
38 public static void StartLogicalOperation() {
37 public static void StartLogicalOperation() {
39 Trace.CorrelationManager.StartLogicalOperation();
38 Trace.CorrelationManager.StartLogicalOperation();
40
39
41 }
40 }
42
41
43 /// <summary>
42 /// <summary>
44 /// Starts the logical operation with the specified name, this name is usefull in logs.
43 /// Starts the logical operation with the specified name, this name is usefull in logs.
45 /// </summary>
44 /// </summary>
46 /// <param name="name">Name.</param>
45 /// <param name="name">Name.</param>
47 #if NETFX_TRACE_BUG
46 #if NETFX_TRACE_BUG
48 public static void StartLogicalOperation(object name) {
47 public static void StartLogicalOperation(object name) {
49 m_currentOperation.Value = name;
48 m_currentOperation.Value = name;
50 Trace.CorrelationManager.StartLogicalOperation(name);
49 Trace.CorrelationManager.StartLogicalOperation(name);
51 }
50 }
52 #else
51 #else
53 public static void StartLogicalOperation(object name) {
52 public static void StartLogicalOperation(object name) {
54 Trace.CorrelationManager.StartLogicalOperation(name);
53 Trace.CorrelationManager.StartLogicalOperation(name);
55 }
54 }
56 #endif
55 #endif
57
56
58 /// <summary>
57 /// <summary>
59 /// Ends the logical operation and restores the previous one.
58 /// Ends the logical operation and restores the previous one.
60 /// </summary>
59 /// </summary>
61 public static void StopLogicalOperation() {
60 public static void StopLogicalOperation() {
62 Trace.CorrelationManager.StopLogicalOperation();
61 Trace.CorrelationManager.StopLogicalOperation();
63 }
62 }
64
63
65 /// <summary>
64 /// <summary>
66 /// Writes a debug message.
65 /// Writes a debug message.
67 /// </summary>
66 /// </summary>
68 /// <param name="format">Format.</param>
67 /// <param name="format">Format.</param>
69 /// <param name="arguments">Arguments.</param>
68 /// <param name="arguments">Arguments.</param>
70 [Conditional("DEBUG")]
69 [Conditional("DEBUG")]
71 public static void Debug(string format, params object[] arguments) {
70 public static void Debug(string format, params object[] arguments) {
72
71
73 }
72 }
74
73
75 /// <summary>
74 /// <summary>
76 /// Writes an informational message.
75 /// Writes an informational message.
77 /// </summary>
76 /// </summary>
78 /// <param name="format">Format.</param>
77 /// <param name="format">Format.</param>
79 /// <param name="arguments">Arguments.</param>
78 /// <param name="arguments">Arguments.</param>
80 [Conditional("TRACE")]
79 [Conditional("TRACE")]
81 public static void Log(string format, params object[] arguments) {
80 public static void Log(string format, params object[] arguments) {
82 TraceSource.TraceEvent(TraceEventType.Information, 0, format, arguments);
81 TraceSource.TraceEvent(TraceEventType.Information, 0, format, arguments);
83 }
82 }
84
83
85 /// <summary>
84 /// <summary>
86 /// Writes a warning message.
85 /// Writes a warning message.
87 /// </summary>
86 /// </summary>
88 /// <param name="format">Format.</param>
87 /// <param name="format">Format.</param>
89 /// <param name="arguments">Arguments.</param>
88 /// <param name="arguments">Arguments.</param>
90 public static void Warn(string format, params object[] arguments) {
89 public static void Warn(string format, params object[] arguments) {
91 TraceSource.TraceEvent(TraceEventType.Warning, 0, format, arguments);
90 TraceSource.TraceEvent(TraceEventType.Warning, 0, format, arguments);
92 }
91 }
93
92
94 /// <summary>
93 /// <summary>
95 /// Writes a error message.
94 /// Writes a error message.
96 /// </summary>
95 /// </summary>
97 /// <param name="format">Format.</param>
96 /// <param name="format">Format.</param>
98 /// <param name="arguments">Arguments.</param>
97 /// <param name="arguments">Arguments.</param>
99 public static void Error(string format, params object[] arguments) {
98 public static void Error(string format, params object[] arguments) {
100 TraceSource.TraceEvent(TraceEventType.Error, 0, format, arguments);
99 TraceSource.TraceEvent(TraceEventType.Error, 0, format, arguments);
101 }
100 }
102
101
103 public static void Error(Exception err) {
102 public static void Error(Exception err) {
104 TraceSource.TraceData(TraceEventType.Error, 0, err);
103 TraceSource.TraceData(TraceEventType.Error, 0, err);
105 }
104 }
106
105
107 /// <summary>
106 /// <summary>
108 /// This method save the current activity, and transfers to the specified activity,
107 /// This method save the current activity, and transfers to the specified activity,
109 /// emits <see cref="TraceEventType.Start"/> and returns a scope of the new
108 /// emits <see cref="TraceEventType.Start"/> and returns a scope of the new
110 /// activity.
109 /// activity.
111 /// </summary>
110 /// </summary>
112 /// <param name="activityName">The name of the new activity/</param>
111 /// <param name="activityName">The name of the new activity/</param>
113 /// <param name="activityId">The identifier of the activity to which
112 /// <param name="activityId">The identifier of the activity to which
114 /// the control will be transferred</param>
113 /// the control will be transferred</param>
115 /// <returns>A scope of the new activity, dispose it to transfer
114 /// <returns>A scope of the new activity, dispose it to transfer
116 /// the control back to the original activity.</returns>
115 /// the control back to the original activity.</returns>
117 public static ActivityScope TransferActivity(string activityName, Guid activityId) {
116 public static ActivityScope TransferActivity(string activityName, Guid activityId) {
118 var prev = Trace.CorrelationManager.ActivityId;
117 var prev = Trace.CorrelationManager.ActivityId;
119
118
120 TraceSource.TraceTransfer(0, "Transfer", activityId);
119 TraceSource.TraceTransfer(0, "Transfer", activityId);
121 Trace.CorrelationManager.ActivityId = activityId;
120 Trace.CorrelationManager.ActivityId = activityId;
122 TraceSource.TraceEvent(TraceEventType.Start, 0, activityName);
121 TraceSource.TraceEvent(TraceEventType.Start, 0, activityName);
123
122
124 return new ActivityScope(TraceSource, prev, 0, activityName);
123 return new ActivityScope(TraceSource, prev, 0, activityName);
125 }
124 }
126
125
127 /// <summary>
126 /// <summary>
128 /// Emits <see cref="TraceEventType.Start"/> and returns a scope of the
127 /// Emits <see cref="TraceEventType.Start"/> and returns a scope of the
129 /// activity.
128 /// activity.
130 /// </summary>
129 /// </summary>
131 /// <param name="activityName">The name of the activity to start</param>
130 /// <param name="activityName">The name of the activity to start</param>
132 /// <returns>A scope of the new activity, dispose it to emit
131 /// <returns>A scope of the new activity, dispose it to emit
133 /// <see cref="TraceEventType.Stop"/> for the current activity.</returns>
132 /// <see cref="TraceEventType.Stop"/> for the current activity.</returns>
134 public static ActivityScope StartActivity(string activityName) {
133 public static ActivityScope StartActivity(string activityName) {
135 if (Trace.CorrelationManager.ActivityId == Guid.Empty)
134 if (Trace.CorrelationManager.ActivityId == Guid.Empty)
136 Trace.CorrelationManager.ActivityId = Guid.NewGuid();
135 Trace.CorrelationManager.ActivityId = Guid.NewGuid();
137
136
138 var prev = Trace.CorrelationManager.ActivityId;
137 var prev = Trace.CorrelationManager.ActivityId;
139
138
140 TraceSource.TraceEvent(TraceEventType.Start, 0, activityName);
139 TraceSource.TraceEvent(TraceEventType.Start, 0, activityName);
141 return new ActivityScope(TraceSource, prev, 0, activityName);
140 return new ActivityScope(TraceSource, prev, 0, activityName);
142 }
141 }
143
142
144 /// <summary>
143 /// <summary>
145 /// Creates new <see cref="LogicalOperation(string)"/> and calls
144 /// Creates new <see cref="LogicalOperation(string)"/> and calls
146 /// to <see cref="CorrelationManager.StartLogicalOperation(object)"/>
145 /// to <see cref="CorrelationManager.StartLogicalOperation(object)"/>
147 /// passing the created operation as identity. Calls
146 /// passing the created operation as identity. Calls
148 /// <see cref="TraceSource.TraceData(TraceEventType, int, object)"/>
147 /// <see cref="TraceSource.TraceData(TraceEventType, int, object)"/>
149 /// to notify listeners on operation start.
148 /// to notify listeners on operation start.
150 /// </summary>
149 /// </summary>
151 /// <param name="name">The name of the logical operation.</param>
150 /// <param name="name">The name of the logical operation.</param>
152 /// <returns>Logical operation scope, disposing it will stop
151 /// <returns>Logical operation scope, disposing it will stop
153 /// logical operation and notify trace listeners.</returns>
152 /// logical operation and notify trace listeners.</returns>
154 public static LogicalOperationScope LogicalOperation(string name) {
153 public static LogicalOperationScope LogicalOperation(string name) {
155 var operation = new LogicalOperation(name);
154 var operation = new LogicalOperation(name);
156 TraceSource.TraceData(TraceEventType.Information, TraceEventCodes.StartLogicalOperation, operation);
155 TraceSource.TraceData(TraceEventType.Information, TraceEventCodes.StartLogicalOperation, operation);
157 StartLogicalOperation(operation);
156 StartLogicalOperation(operation);
158 return new LogicalOperationScope(TraceSource, operation);
157 return new LogicalOperationScope(TraceSource, operation);
159 }
158 }
160 }
159 }
161 }
160 }
@@ -1,127 +1,128
1 using Implab.Automaton;
1 using Implab.Automaton;
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.Runtime.CompilerServices;
6 using System.Runtime.CompilerServices;
7 using System.Text;
7 using System.Text;
8 using System.Threading.Tasks;
8 using System.Threading.Tasks;
9
9
10 namespace Implab.Formats {
10 namespace Implab.Formats {
11
11
12 /// <summary>
12 /// <summary>
13 /// Fast input scanner for max 255 states and first 255 input chacters.
13 /// Fast input scanner for max 255 states and 255 input chacters.
14 /// </summary>
14 /// </summary>
15 /// <typeparam name="TTag"></typeparam>
15 /// <typeparam name="TTag"></typeparam>
16 /// <remarks>
16 /// <remarks>
17 /// Creates a one rank array to store automa transition table, each entry in this table is byte, to make this table fit into L1 cache.
17 /// <para>
18 ///
18 /// Creates a one rank array to store automa transition table, each entry in this table is byte, to make this table small enough to fit L1 cache.
19 /// Each entry is addressed as <c>(state << 8) | input</c> which make this quite fast to get the next state.
19 /// </para>
20 ///
20 /// <para>
21 /// Each input symbol below 255 is treated as 255.
21 /// Each entry is addressed as <c>(state << 8) | input</c> which make this quite fast to get the next state. Each input symbol below 255 is treated as 255.
22 /// </para>
22 /// </remarks>
23 /// </remarks>
23 public class FastInputScanner<TTag> {
24 public class FastInputScanner<TTag> {
24 const int StateShift = 8;
25 const int StateShift = 8;
25 const int StateMask = ~((1 << StateShift) - 1);
26 const int StateMask = ~((1 << StateShift) - 1);
26 const int AlphabetSize = 1 << StateShift;
27 const int AlphabetSize = 1 << StateShift;
27 const int UnclassifiedInput = (1 << StateShift) - 1;
28 const int UnclassifiedInput = (1 << StateShift) - 1;
28 const byte UnreachableState = byte.MaxValue;
29 const byte UnreachableState = byte.MaxValue;
29
30
30 readonly TTag[] m_tags;
31 readonly TTag[] m_tags;
31 readonly bool[] m_final;
32 readonly bool[] m_final;
32
33
33 readonly byte m_initialState;
34 readonly byte m_initialState;
34 readonly byte[] m_dfa;
35 readonly byte[] m_dfa;
35
36
36 int m_position;
37 int m_position;
37 byte m_state;
38 byte m_state;
38
39
39 protected FastInputScanner(byte[] table, bool[] final, TTag[] tags, byte initial) {
40 protected FastInputScanner(byte[] table, bool[] final, TTag[] tags, byte initial) {
40 m_dfa = table;
41 m_dfa = table;
41 m_final = final;
42 m_final = final;
42 m_tags = tags;
43 m_tags = tags;
43 m_initialState = initial;
44 m_initialState = initial;
44 }
45 }
45
46
46 public FastInputScanner(int[,] dfaTable, bool[] finalStates, TTag[] tags, int initialState, int[] inputMap) {
47 public FastInputScanner(int[,] dfaTable, bool[] finalStates, TTag[] tags, int initialState, int[] inputMap) {
47 var states = dfaTable.GetLength(0);
48 var states = dfaTable.GetLength(0);
48 Debug.Assert(states < byte.MaxValue);
49 Debug.Assert(states < byte.MaxValue);
49
50
50 m_dfa = new byte[states << StateShift];
51 m_dfa = new byte[states << StateShift];
51 m_initialState = (byte)initialState;
52 m_initialState = (byte)initialState;
52
53
53 m_tags = tags;
54 m_tags = tags;
54 m_final = finalStates;
55 m_final = finalStates;
55
56
56 // iterate over states
57 // iterate over states
57 for(int si = 0; si < states; si++) {
58 for(int si = 0; si < states; si++) {
58 // state offset for the new table
59 // state offset for the new table
59 var offset = si << StateShift;
60 var offset = si << StateShift;
60
61
61 // iterate over alphabet
62 // iterate over alphabet
62 for(int a = 0; a < AlphabetSize; a++) {
63 for(int a = 0; a < AlphabetSize; a++) {
63 var next = dfaTable[si, a < inputMap.Length ? inputMap[a] : AutomatonConst.UnclassifiedInput];
64 var next = dfaTable[si, a < inputMap.Length ? inputMap[a] : AutomatonConst.UnclassifiedInput];
64 if (next == AutomatonConst.UnreachableState)
65 if (next == AutomatonConst.UnreachableState)
65 next = UnreachableState;
66 next = UnreachableState;
66
67
67 m_dfa[offset | a] = (byte)next;
68 m_dfa[offset | a] = (byte)next;
68 }
69 }
69 }
70 }
70 }
71 }
71
72
72 public TTag Tag {
73 public TTag Tag {
73 [MethodImpl(MethodImplOptions.AggressiveInlining)]
74 [MethodImpl(MethodImplOptions.AggressiveInlining)]
74 get {
75 get {
75 return m_tags[m_state];
76 return m_tags[m_state];
76 }
77 }
77 }
78 }
78
79
79 public int Position {
80 public int Position {
80 [MethodImpl(MethodImplOptions.AggressiveInlining)]
81 [MethodImpl(MethodImplOptions.AggressiveInlining)]
81 get {
82 get {
82 return m_position;
83 return m_position;
83 }
84 }
84 }
85 }
85
86
86 public bool IsFinal {
87 public bool IsFinal {
87 [MethodImpl(MethodImplOptions.AggressiveInlining)]
88 [MethodImpl(MethodImplOptions.AggressiveInlining)]
88 get {
89 get {
89 return m_final[m_state];
90 return m_final[m_state];
90 }
91 }
91 }
92 }
92
93
93 [MethodImpl(MethodImplOptions.AggressiveInlining)]
94 [MethodImpl(MethodImplOptions.AggressiveInlining)]
94 public void ResetState() {
95 public void ResetState() {
95 m_state = m_initialState;
96 m_state = m_initialState;
96 }
97 }
97
98
98 public FastInputScanner<TTag> Clone() {
99 public FastInputScanner<TTag> Clone() {
99 var clone = new FastInputScanner<TTag>(m_dfa, m_final, m_tags, m_initialState);
100 var clone = new FastInputScanner<TTag>(m_dfa, m_final, m_tags, m_initialState);
100 clone.m_state = m_state;
101 clone.m_state = m_state;
101 clone.m_position = m_position;
102 clone.m_position = m_position;
102 return clone;
103 return clone;
103 }
104 }
104
105
105 public bool Scan(char[] data, int offset, int max) {
106 public bool Scan(char[] data, int offset, int max) {
106 var next = m_state;
107 var next = m_state;
107
108
108 m_position = offset;
109 m_position = offset;
109 while (m_position < max) {
110 while (m_position < max) {
110 var ch = data[m_position];
111 var ch = data[m_position];
111
112
112 next = m_dfa[(ch >= AlphabetSize ? (next << StateShift) | UnclassifiedInput : (next << StateShift) | ch)];
113 next = m_dfa[(ch >= AlphabetSize ? (next << StateShift) | UnclassifiedInput : (next << StateShift) | ch)];
113
114
114 if (next == UnreachableState)
115 if (next == UnreachableState)
115 // scanner stops at the next position after the last recognized symbol
116 // scanner stops at the next position after the last recognized symbol
116 return false;
117 return false;
117
118
118 m_state = next;
119 m_state = next;
119 m_position++;
120 m_position++;
120 }
121 }
121
122
122 return true;
123 return true;
123 }
124 }
124
125
125
126
126 }
127 }
127 }
128 }
@@ -1,140 +1,115
1 using System.Threading;
1 using System.Threading;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System;
3 using System;
4 using System.Collections;
4 using System.Collections;
5
5
6 namespace Implab.Parallels {
6 namespace Implab.Parallels {
7
8 /// <summary>
9 /// Very simple thred-safe FIFO queue based on the sinle linked list.
10 /// </summary>
11 /// <typeparam name="T"></typeparam>
12 /// <remarks>
13 /// This queue uses interlocked operations to add and remove nodes,
14 /// each node stores a single value. The queue provides mean performance,
15 /// moderate overhead and situable for a small amount of elements.
16 /// </remarks>
7 public class SimpleAsyncQueue<T> : IEnumerable<T> {
17 public class SimpleAsyncQueue<T> : IEnumerable<T> {
8 class Node {
18 class Node {
9 public Node(T value) {
19 public Node(T value) {
10 this.value = value;
20 this.value = value;
11 }
21 }
12 public readonly T value;
22 public readonly T value;
13 public volatile Node next;
23 public volatile Node next;
14 }
24 }
15
25
16 // the reader and the writer are mainteined completely independent,
26 // the reader and the writer are maintained completely independent,
17 // the reader can read next item when m_first.next is not null
27 // the reader can read next item when m_first.next is not null
18 // the writer creates a new node, moves m_last to this node and
28 // the writer creates a new node, moves m_last to this node and
19 // only after that restores the reference from the previous node
29 // only after that restores the reference from the previous node
20 // making the reader be able to read the new node.
30 // making the reader able to read the new node.
21
31
22 volatile Node m_first; // position on the node which is already read
32 volatile Node m_first; // position on the node which is already read
23 volatile Node m_last; // position on the node which is already written
33 volatile Node m_last; // position on the node which is already written
24
34
25 public SimpleAsyncQueue() {
35 public SimpleAsyncQueue() {
26 m_first = m_last = new Node(default(T));
36 m_first = m_last = new Node(default(T));
27 }
37 }
28
38
29 public void Enqueue(T value) {
39 public void Enqueue(T value) {
30 var next = new Node(value);
40 var next = new Node(value);
31
41
32 // Interlocaked.CompareExchange implies Thread.MemoryBarrier();
42 // Interlocaked.CompareExchange implies Thread.MemoryBarrier();
33 // to ensure that the next node is completely constructed
43 // to ensure that the next node is completely constructed
34 var last = Interlocked.Exchange(ref m_last, next);
44 var last = Interlocked.Exchange(ref m_last, next);
35
45
36 // release-fence
46 // release-fence
37 last.next = next;
47 last.next = next;
38
48
39 }
49 }
40
50
41 public bool TryDequeue(out T value) {
51 public bool TryDequeue(out T value) {
42 Node first = m_first; ;
52 Node first = m_first;
43 Node next = first.next; ;
53 Node next = first.next;
44
54
45 if (next == null) {
55 if (next == null) {
46 value = default(T);
56 value = default(T);
47 return false;
57 return false;
48 }
58 }
49
59
50 var first2 = Interlocked.CompareExchange(ref m_first, next, first);
60 var first2 = Interlocked.CompareExchange(ref m_first, next, first);
51
61
52 if (first != first2) {
62 if (first != first2) {
53 // head is updated by someone else
63 // head is updated by someone else
54
64
55 SpinWait spin = new SpinWait();
65 SpinWait spin = new SpinWait();
56 do {
66 do {
57 first = first2;
67 first = first2;
58 next = first.next;
68 next = first.next;
59 if (next == null) {
69 if (next == null) {
60 value = default(T);
70 value = default(T);
61 return false;
71 return false;
62 }
72 }
63
73
64 first2 = Interlocked.CompareExchange(ref m_first, next, first);
74 first2 = Interlocked.CompareExchange(ref m_first, next, first);
65 if (first == first2)
75 if (first == first2)
66 break;
76 break;
67 spin.SpinOnce();
77 spin.SpinOnce();
68 } while (true);
78 } while (true);
69 }
79 }
70
80
71 value = next.value;
81 value = next.value;
72 return true;
82 return true;
73 }
83 }
74
84
75 #region IEnumerable implementation
85 /// <summary>
76
86 /// Creates a thin copy of the current linked list.
77 class Enumerator : IEnumerator<T> {
87 /// </summary>
78 Node m_current;
88 /// <remarks>Iterating over the snapshot is thread safe and
79 Node m_first;
89 /// will produce repeatble results. Each snapshot stores only
80
90 /// two references one for the first and one for last elements
81 public Enumerator(Node first) {
91 /// from list.
82 m_first = first;
92 /// <returns>Enumerable collection.</returns>
83 }
93 public IEnumerable<T> Snapshot() {
84
94 var first = m_first;
85 #region IEnumerator implementation
95 var last = m_last;
86
96
87 public bool MoveNext() {
97 var current = m_first;
88 m_current = m_current == null ? m_first : m_current.next;
98 while(current != m_last) {
89 return m_current != null;
99 current = current.next;
90 }
100 yield return current.value;
91
92 public void Reset() {
93 m_current = null;
94 }
95
96 object IEnumerator.Current {
97 get {
98 if (m_current == null)
99 throw new InvalidOperationException();
100 return m_current.value;
101 }
101 }
102 }
102 }
103
103
104 #endregion
104 public IEnumerator<T> GetEnumerator() {
105
105 for (var current = m_first.next; current != null; current = current.next) {
106 #region IDisposable implementation
106 yield return current.value;
107
108 public void Dispose() {
109 }
110
111 #endregion
112
113 #region IEnumerator implementation
114
115 public T Current {
116 get {
117 if (m_current == null)
118 throw new InvalidOperationException();
119 return m_current.value;
120 }
107 }
121 }
108 }
122
109
123 #endregion
124 }
125
126 public IEnumerator<T> GetEnumerator() {
127 return new Enumerator(m_first);
128 }
129
130 #endregion
131
132 #region IEnumerable implementation
133
134 IEnumerator IEnumerable.GetEnumerator() {
110 IEnumerator IEnumerable.GetEnumerator() {
135 return GetEnumerator();
111 return GetEnumerator();
136 }
112 }
137
113
138 #endregion
139 }
114 }
140 }
115 }
1 NO CONTENT: file was removed
NO CONTENT: file was removed
General Comments 3
Under Review
author

Auto status change to "Under Review"

Approved
author

ok, latest stable version should be in default

You need to be logged in to leave comments. Login now