##// END OF EJS Templates
Working on Implab.Diagnostics
Working on Implab.Diagnostics

File last commit:

r285:b6924f444abd v3
r286:67ebcfd7d1c8 v3
Show More
TraceChannelRegistry.cs
75 lines | 2.3 KiB | text/x-csharp | CSharpLexer
using System;
using System.Collections.Generic;
using System.Diagnostics;
using Implab.Parallels;
namespace Implab.Diagnostics {
public class TraceChannelRegistry {
class Subscription : IDisposable {
readonly Action<object> m_unsubscribe;
public Subscription(Action<object> unsubscribe) {
m_unsubscribe = unsubscribe;
}
public void Dispose() {
m_unsubscribe(this);
}
}
public static TraceChannelRegistry AllCannels { get; } = new TraceChannelRegistry();
readonly object m_lock = new object();
readonly Dictionary<object, Action<ChannelInfo>> m_subscriptions = new Dictionary<object, Action<ChannelInfo>>();
readonly SimpleAsyncQueue<ChannelInfo> m_channels = new SimpleAsyncQueue<ChannelInfo>();
internal void NotifyChannelCreated(ChannelInfo channel) {
// notifications can run in parallel
Action<ChannelInfo>[] handlers = null;
lock(m_lock) {
m_channels.Enqueue(channel);
if (m_subscriptions.Count > 0) {
handlers = new Action<ChannelInfo>[m_subscriptions.Count];
m_subscriptions.Values.CopyTo(handlers, 0);
}
}
if (handlers != null)
foreach(var h in handlers)
h(channel);
}
/// <summary>
/// Subscribes the specified handler to notifications about new trace
/// channels
/// </summary>
/// <param name="handler"></param>
/// <returns></returns>
public IDisposable Subscribe(Action<ChannelInfo> handler, bool existing) {
Safe.ArgumentNotNull(handler, nameof(handler));
var cookie = new Subscription(RemoveSubscription);
IEnumerable<ChannelInfo> snap;
lock(m_lock) {
m_subscriptions.Add(cookie, handler);
snap = m_channels.Snapshot();
}
if (existing) {
foreach(var c in snap)
handler(c);
}
return cookie;
}
void RemoveSubscription(object cookie) {
lock(m_lock)
m_subscriptions.Remove(cookie);
}
}
}