public Node(Node parent, int key, int depth) { this.Parent = parent; this.Key = key; this.Depth = depth; this.Children = new ConcurrentDictionary<int, Node>(); this.Subscribers = new ConcurrentDictionary<object, object>(); this.RefCount = 0; this.SyncRoot = new object(); }
public void Add(int[] hashPath, object subscriber) { if (hashPath.Length < Depth) throw new InvalidOperationException(); if(hashPath.Length == Depth + 1) { IncRefCount(); // In this case, subscriber already exists in the collection. if (!Subscribers.TryAdd(subscriber, subscriber)) { DecRefCount(); throw new InvalidOperationException(); } } else { IncRefCount(); int key = hashPath[Depth + 1]; Node node; if (!Children.TryGetValue(key, out node)) { // 'lock' must be placed here, // cause there is a potential problem which makes a orpahned node. lock (SyncRoot) { // double-checking for reducing the overheads from 'lock' if(!Children.TryGetValue(key, out node)) { node = new Node(this, key, Depth + 1); Children.TryAdd(key, node); } } } node.Add(hashPath, subscriber); } }
public Pubsub() { this.Root = new Node(null, 0, -1); // Each threads has its own thread-local-cache storage. this.PathCache = new ThreadLocal<Dictionary<string, WeakReference<Channel>>>( ()=>{ return new Dictionary<string, WeakReference<Channel>>(); }); }