public IAsyncResult BeginAdd(Message msg, ulong id, AsyncCallback cb, object state)
            {
                try
                {
                    this.rwLock.EnterWriteLock();
                    this.PurgeExpired();

                    var cmsg = new CachedMessage(msg.SignalKey, msg.Value, msg.Created, id);
                    if (this.messageIndex.Count + 1 < CapacityLimit)
                    {
                        // add and complete
                        this.AddToCache(cmsg);
                        return new CompletedAsyncResult(cb, state);
                    }
                    else
                    {
                        // move the 'Add' operation to pending until we've got room to 
                        // add the item and complete once the item has been dequeued
                        // calling Complete on the AR
                        var addAsyncResult = new AddAsyncResult(cb, state);
                        this.pendingAdds.EnqueueAndDispatch(cmsg, addAsyncResult.Complete);
                        return addAsyncResult;
                    }
                }
                finally
                {
                    this.rwLock.ExitWriteLock();
                }
            }
            void AddToCache(CachedMessage msg)
            {
                try
                {
                    this.rwLock.EnterWriteLock();
                    this.messageIndex.Add(msg.Id, msg);
                }
                finally
                {
                    this.rwLock.ExitWriteLock();
                }

                // swap the pending gets queue so that we can drain the old 
                // one and re-enqueue what we can't service right now
                var copiedPendingNotifications = Interlocked.Exchange(ref this.pendingNotifications, new InputQueue<NotificationRegistration>());
                for (; ; )
                {
                    NotificationRegistration notificationRegistration;
                    if (copiedPendingNotifications.Dequeue(TimeSpan.Zero, out notificationRegistration))
                    {
                        if (!notificationRegistration.Cancelled)
                        {
                            if (notificationRegistration.EventKey.Equals(msg.SignalKey))
                            {
                                SimpleIOThreadScheduler.ScheduleCallback(
                                                                         (pg) => ((NotificationRegistration)pg).Callback(),
                                                                         (e) => true,
                                                                         notificationRegistration);
                            }
                            else
                            {
                                this.pendingNotifications.EnqueueWithoutDispatch(notificationRegistration, null);
                            }
                        }
                    }
                    else
                    {
                        break;
                    }
                }
            }