Esempio n. 1
0
        // TODO: Put strings into the resources.
        //
        async Task ILocalSubscriber.OnSubscriptionActivationAsync(ILocalSubscription subscription, IContext ctx)
        {
            subscription.EnsureNotNull(nameof(subscription));
            //
            if (!ReferenceEquals(objA: subscription.Subscriber, objB: this))
            {
                throw
                    new ArgumentOutOfRangeException(
                        paramName: nameof(subscription),
                        message: $"Указанная подписка не относится к данному подписчику.{Environment.NewLine}\tПодписка:{subscription.FmtStr().GNLI2()}{Environment.NewLine}\tПодписчик:{this.FmtStr().GNLI2()}");
            }
            else if (!ReferenceEquals(ReadDA(ref _activatedSubscription), subscription))
            {
                ILocalSubscription original;
                var lck         = ReadDA(ref _processMessagePostLock);
                var lckAcquired = false;
                try {
                    lckAcquired = await lck.WaitAsync(millisecondsTimeout : TaskUtilities.DefaultAsyncTimeoutMilliseconds, cancellationToken : ctx.Ct()).ConfigureAwait(false);

                    if (!lckAcquired)
                    {
                        throw new LockAcquisitionFailException(reason: LockAcquisitionFailReason.TimeoutElapsed);
                    }
                    //
                    if (!((original = WriteDA(ref _activatedSubscription, subscription, null)) == null || ReferenceEquals(original, subscription)))
                    {
                        throw
                            new InvalidOperationException(
                                $"Невозможно активировать еще одну подписку для данного подписчика. Подписчик не поддерживает работу с несколькими подписками.{Environment.NewLine}\tПодписка:{Environment.NewLine}{subscription.FmtStr().GI2()}{Environment.NewLine}\tПодписчик:{Environment.NewLine}{this.FmtStr().GI2()}");
                    }
                    else if (original == null)
                    {
                        try {
                            await OnSubscriptionActivationAsync(subscription : subscription, ctx : ctx).ConfigureAwait(false);
                        }
                        catch {
                            Interlocked.CompareExchange(ref _activatedSubscription, original, subscription);
                            throw;
                        }
                    }
                }
                finally {
                    if (lckAcquired)
                    {
                        try { lck.Release(); }
                        catch (ObjectDisposedException) { }
                    }
                }
            }
        }
Esempio n. 2
0
        // TODO: Put strings into the resources.
        //
        async Task ILocalSubscriber.OnSubscriptionDeactivationAsync(ILocalSubscription subscription, IContext ctx)
        {
            subscription.EnsureNotNull(nameof(subscription));
            //
            if (ReferenceEquals(subscription, ReadDA(ref _activatedSubscription)))
            {
                var lck         = ReadDA(ref _processMessagePostLock);
                var lckAcquired = false;
                try {
                    lckAcquired = await lck.WaitAsync(millisecondsTimeout : TaskUtilities.DefaultAsyncTimeoutMilliseconds, cancellationToken : ctx.Ct()).ConfigureAwait(false);

                    if (!lckAcquired)
                    {
                        throw new LockAcquisitionFailException(reason: LockAcquisitionFailReason.TimeoutElapsed);
                    }
                    //
                    await OnSubscriptionDeactivationAsync(subscription : subscription, ctx : ctx).ConfigureAwait(false);

                    Interlocked.CompareExchange(ref _activatedSubscription, null, comparand: subscription);
                }
                finally {
                    if (lckAcquired)
                    {
                        try { lck.Release(); }
                        catch (ObjectDisposedException) { }
                    }
                }
            }
            else
            {
                throw
                    new InvalidOperationException(
                        $"Недопустимый вызов операции деактивации подписки для данного подписчика. Указанная подписка не была активирована для подписчика.{Environment.NewLine}\tПодписка:{subscription.FmtStr().GNLI2()}{Environment.NewLine}\tПодписчик:{this.FmtStr().GNLI2()}");
            }
        }
Esempio n. 3
0
 // TODO: Put strings into the resources.
 //
 public Task <ILocalSubscription> SubscribeAsync(ILocalSubscription subscription)
 {
     try {
         subscription.EnsureNotNull(nameof(subscription));
         if (!ReferenceEquals(subscription.Publisher, this))
         {
             throw
                 new ArgumentOutOfRangeException(
                     paramName: nameof(subscription),
                     message: $"Subscription is not associated with this publisher.{Environment.NewLine}\tSubscription:{subscription.FmtStr().GNLI2()}{Environment.NewLine}\tPublisher:{this.FmtStr().GNLI2()}");
         }
         //
         var spinLock = ReadDA(ref _subscriptionsSpinLock);
         var subscriptionsDictionary          = ReadDA(ref _subscriptionsDictionary);
         var subscriptionsList                = ReadDA(ref _subscriptionsList);
         var existingSubscriptionRegistration = default(P_NewSubscriptionRegistrationState);
         //
         if (!spinLock.Invoke(() => subscriptionsDictionary.TryGetValue(subscription, out existingSubscriptionRegistration)))
         {
             var newSubscriptionRegistration = default(P_NewSubscriptionRegistrationState);
             try {
                 newSubscriptionRegistration = new P_NewSubscriptionRegistrationState(subscription);
                 spinLock
                 .Invoke(
                     () => {
                     EnsureNotDisposeState();
                     //
                     if (subscriptionsDictionary.ContainsKey(subscription))
                     {
                         existingSubscriptionRegistration = subscriptionsDictionary[subscription];
                     }
                     else
                     {
                         subscriptionsDictionary.Add(subscription, newSubscriptionRegistration);
                         existingSubscriptionRegistration = newSubscriptionRegistration;
                         subscriptionsList.Add(newSubscriptionRegistration.Subscription);
                     }
                 });
                 if (existingSubscriptionRegistration == newSubscriptionRegistration)
                 {
                     subscription
                     .ActivateAsync()
                     .ContinueWith(
                         locActivateTask => {
                         if (locActivateTask.IsCanceled)
                         {
                             newSubscriptionRegistration.SubscribeTaskProxy.TrySetCanceled();
                         }
                         else if (locActivateTask.IsFaulted)
                         {
                             if (!newSubscriptionRegistration.SubscribeTaskProxy.TrySetException(locActivateTask.Exception))
                             {
                                 throw new AggregateException(locActivateTask.Exception);
                             }
                         }
                         else
                         {
                             newSubscriptionRegistration.SubscribeTaskProxy.TrySetResult(newSubscriptionRegistration.Subscription);
                         }
                     },
                         TaskContinuationOptions.ExecuteSynchronously);
                 }
             }
             catch (Exception firstException) {
                 newSubscriptionRegistration?.SubscribeTaskProxy.TrySetException(firstException);
                 throw;
             }
             finally {
                 if (newSubscriptionRegistration != existingSubscriptionRegistration)
                 {
                     newSubscriptionRegistration?.SubscribeTaskProxy.TrySetCanceled();
                 }
             }
         }
         //
         return(existingSubscriptionRegistration.SubscribeTaskProxy.Task);
     }
     catch (Exception firstException) {
         return(TaskUtilities.FromError <ILocalSubscription>(firstException));
     }
 }