// 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) { } } } } }
// 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()}"); } }
// 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)); } }