Beispiel #1
0
            // Create a new linked list where 'subscription has been removed from the linked list of 'subscriptions'.
            private static DiagnosticSubscription Remove(DiagnosticSubscription subscriptions, DiagnosticSubscription subscription)
            {
                if (subscriptions == null)
                {
                    // May happen if the IDisposable returned from Subscribe is Dispose'd again
                    return(null);
                }

                if (subscriptions.Observer == subscription.Observer &&
                    subscriptions.IsEnabled1Arg == subscription.IsEnabled1Arg &&
                    subscriptions.IsEnabled3Arg == subscription.IsEnabled3Arg)
                {
                    return(subscriptions.Next);
                }
#if DEBUG
                // Delay a bit.  This makes it more likely that races will happen.
                for (int i = 0; i < 100; i++)
                {
                    GC.KeepAlive("");
                }
#endif
                return(new DiagnosticSubscription()
                {
                    Observer = subscriptions.Observer, Owner = subscriptions.Owner, IsEnabled1Arg = subscriptions.IsEnabled1Arg, IsEnabled3Arg = subscriptions.IsEnabled3Arg, Next = Remove(subscriptions.Next, subscription)
                });
            }
Beispiel #2
0
        private IDisposable SubscribeInternal(IObserver <KeyValuePair <string, object> > observer,
                                              Predicate <string> isEnabled1Arg, Func <string, object, object, bool> isEnabled3Arg,
                                              Action <Activity, object> onActivityImport, Action <Activity, object> onActivityExport)
        {
            // If we have been disposed, we silently ignore any subscriptions.
            if (_disposed)
            {
                return(new DiagnosticSubscription()
                {
                    Owner = this
                });
            }
            DiagnosticSubscription newSubscription = new DiagnosticSubscription()
            {
                Observer         = observer,
                IsEnabled1Arg    = isEnabled1Arg,
                IsEnabled3Arg    = isEnabled3Arg,
                OnActivityImport = onActivityImport,
                OnActivityExport = onActivityExport,
                Owner            = this,
                Next             = _subscriptions
            };

            while (Interlocked.CompareExchange(ref _subscriptions, newSubscription, newSubscription.Next) != newSubscription.Next)
            {
                newSubscription.Next = _subscriptions;
            }
            return(newSubscription);
        }
Beispiel #3
0
 /// <summary>
 /// Override abstract method
 /// </summary>
 public override void Write(string name, object value)
 {
     for (DiagnosticSubscription curSubscription = _subscriptions; curSubscription != null; curSubscription = curSubscription.Next)
     {
         curSubscription.Observer.OnNext(new KeyValuePair <string, object>(name, value));
     }
 }
 public override void OnActivityExport(Activity activity, object payload)
 {
     for (DiagnosticSubscription curSubscription = _subscriptions; curSubscription != null; curSubscription = curSubscription.Next)
     {
         curSubscription.OnActivityExport?.Invoke(activity, payload);
     }
 }
Beispiel #5
0
 // NotificationSource implementation
 /// <summary>
 /// Override abstract method
 /// </summary>
 public override bool IsEnabled(string name, object arg1, object arg2 = null)
 {
     for (DiagnosticSubscription curSubscription = _subscriptions; curSubscription != null; curSubscription = curSubscription.Next)
     {
         if (curSubscription.IsEnabled3Arg == null || curSubscription.IsEnabled3Arg(name, arg1, arg2))
         {
             return(true);
         }
     }
     return(false);
 }
 // NotificationSource implementation
 /// <summary>
 /// Override abstract method
 /// </summary>
 public override bool IsEnabled(string name)
 {
     for (DiagnosticSubscription curSubscription = _subscriptions; curSubscription != null; curSubscription = curSubscription.Next)
     {
         if (curSubscription.IsEnabled == null || curSubscription.IsEnabled(name))
         {
             return(true);
         }
     }
     return(false);
 }
Beispiel #7
0
        /// <summary>
        /// Clean up the NotificationListeners.   Notification listeners do NOT DIE ON THEIR OWN
        /// because they are in a global list (for discoverability).  You must dispose them explicitly.
        /// Note that we do not do the Dispose(bool) pattern because we frankly don't want to support
        /// subclasses that have non-managed state.
        /// </summary>
        public virtual void Dispose()
        {
            // Remove myself from the list of all listeners.
            lock (s_allListenersLock)
            {
                if (_disposed)
                {
                    return;
                }
                _disposed = true;
                if (s_allListeners == this)
                {
                    s_allListeners = s_allListeners._next;
                }
                else
                {
                    var cur = s_allListeners;
                    while (cur != null)
                    {
                        if (cur._next == this)
                        {
                            cur._next = _next;
                            break;
                        }
                        cur = cur._next;
                    }
                }
                _next = null;
            }

            // Indicate completion to all subscribers.
            DiagnosticSubscription subscriber = null;

            Interlocked.Exchange(ref subscriber, _subscriptions);
            while (subscriber != null)
            {
                subscriber.Observer.OnCompleted();
                subscriber = subscriber.Next;
            }
            // The code above also nulled out all subscriptions.
        }
        // Subscription implementation
        /// <summary>
        /// Add a subscriber (Observer).  If 'IsEnabled' == null (or not present), then the Source's IsEnabled
        /// will always return true.
        /// </summary>
        virtual public IDisposable Subscribe(IObserver <KeyValuePair <string, object> > observer, Predicate <string> isEnabled)
        {
            // If we have been disposed, we silently ignore any subscriptions.
            if (_disposed)
            {
                return(new DiagnosticSubscription()
                {
                    Owner = this
                });
            }
            DiagnosticSubscription newSubscription = new DiagnosticSubscription()
            {
                Observer = observer, IsEnabled = isEnabled, Owner = this, Next = _subscriptions
            };

            while (Interlocked.CompareExchange(ref _subscriptions, newSubscription, newSubscription.Next) != newSubscription.Next)
            {
                newSubscription.Next = _subscriptions;
            }
            return(newSubscription);
        }
Beispiel #9
0
            internal DiagnosticSubscription Next;       // Linked list of subscribers

            public void Dispose()
            {
                // TO keep this lock free and easy to analyze, the linked list is READ ONLY.   Thus we copy
                for (; ;)
                {
                    DiagnosticSubscription subscriptions    = Owner._subscriptions;
                    DiagnosticSubscription newSubscriptions = Remove(subscriptions, this);    // Make a new list, with myself removed.

                    // try to update, but if someone beat us to it, then retry.
                    if (Interlocked.CompareExchange(ref Owner._subscriptions, newSubscriptions, subscriptions) == subscriptions)
                    {
#if DEBUG
                        var cur = newSubscriptions;
                        while (cur != null)
                        {
                            Debug.Assert(!(cur.Observer == Observer && cur.IsEnabled1Arg == IsEnabled1Arg && cur.IsEnabled3Arg == IsEnabled3Arg), "Did not remove subscription!");
                            cur = cur.Next;
                        }
#endif
                        break;
                    }
                }
            }