public override bool AddEvent(string eventKey, Topic topic)
        {
            base.AddEvent(eventKey, topic);

            lock (_cursors)
            {
                // O(n), but small n and it's not common
                var index = FindCursorIndex(eventKey);
                if (index == -1)
                {
                    _cursors.Add(new Cursor(eventKey, GetMessageId(topic), _stringMinifier.Minify(eventKey)));

                    _cursorTopics.Add(topic);

                    return true;
                }

                return false;
            }
        }
 public virtual void SetEventTopic(string key, Topic topic)
 {
     // Don't call AddEvent since that's virtual
     AddEventCore(key);
 }
 public virtual bool AddEvent(string key, Topic topic)
 {
     return AddEventCore(key);
 }
        private static ulong GetMessageId(Topic topic)
        {
            if (topic == null)
            {
                return 0;
            }

            return topic.Store.GetMessageCount();
        }
        public override void SetEventTopic(string eventKey, Topic topic)
        {
            base.SetEventTopic(eventKey, topic);

            lock (_cursors)
            {
                // O(n), but small n and it's not common
                var index = FindCursorIndex(eventKey);
                if (index != -1)
                {
                    _cursorTopics[index] = topic;
                }
            }
        }
        private void DestroyTopicCore(string key, Topic topic)
        {
            Topics.TryRemove(key);
            _stringMinifier.RemoveUnminified(key);

            Counters.MessageBusTopicsCurrent.Decrement();

            _logger.LogInformation("RemoveTopic(" + key + ")");

            if (AfterTopicGarbageCollected != null)
            {
                AfterTopicGarbageCollected(key, topic);
            }
        }
 private void DestroyTopic(string key, Topic topic)
 {
     // The goal of this function is to destroy topics after 2 garbage collect cycles
     // This first if statement will transition a topic into the dying state on the first GC cycle 
     // but it will prevent the code path from hitting the second if statement
     if (Interlocked.CompareExchange(ref topic.State, TopicState.Dying, TopicState.NoSubscriptions) == TopicState.Dying)
     {
         // If we've hit this if statement we're on the second GC cycle with this soon to be
         // destroyed topic.  At this point we move the Topic State into the Dead state as
         // long as it has not been revived from the dying state.  We check if the state is
         // still dying again to ensure that the topic has not been transitioned into a new
         // state since we've decided to destroy it.
         if (Interlocked.CompareExchange(ref topic.State, TopicState.Dead, TopicState.Dying) == TopicState.Dying)
         {
             DestroyTopicCore(key, topic);
         }
     }
 }
        private void ScheduleTopic(Topic topic)
        {
            try
            {
                topic.SubscriptionLock.EnterReadLock();

                for (int i = 0; i < topic.Subscriptions.Count; i++)
                {
                    ISubscription subscription = topic.Subscriptions[i];
                    _broker.Schedule(subscription);
                }
            }
            finally
            {
                topic.SubscriptionLock.ExitReadLock();
            }
        }