/// <summary>
        /// Can be disposed from any thread
        /// </summary>
        /// <returns></returns>
        public async Task <IDisposable> LockWriteAsync(int millisecondsTimeout = int.MaxValue)
        {
            MyLockQueueItem queueItem;
            IDisposable     answer;

            lock (_lock)
            {
                // If there's no items
                if (_queue.Count == 0)
                {
                    // Create a new write entry
                    var newEntry = new MyWriteLockQueueItem(this, true);

                    // Add it to the queue
                    _queue.Add(newEntry);

                    // We're already locked, so just return instantly
                    return(new MyDisposableLock(newEntry));
                }

                // Otherwise, we always just add for write locks
                else
                {
                    var newEntry = new MyWriteLockQueueItem(this, alreadyLocked: false);

                    _queue.Add(newEntry);

                    queueItem = newEntry;
                    answer    = new MyDisposableLock(newEntry);
                }
            }

            try
            {
                await TimeoutTask.Create(queueItem.LockedTask, millisecondsTimeout);
            }
            catch (TimeoutException)
            {
                queueItem.Release();
                throw new TimeoutException("Timeout exceeded and lock not established.");
            }
            return(answer);
        }
Beispiel #2
0
        public override async Task <string> GetPushChannelUri()
        {
            if (_channel == null)
            {
                try
                {
                    _channel = await TimeoutTask.Create(PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync().AsTask(), 3000);
                }
                catch (OperationCanceledException)
                {
                    TelemetryExtension.Current?.TrackEvent("CreatePushChannel_TimeoutExceeded");
                }
                catch (Exception)
                {
                    return(null);
                }
                _channel.PushNotificationReceived += _channel_PushNotificationReceived;
            }

            return(_channel.Uri.ToString());
        }
        /// <summary>
        /// Can be disposed from any thread
        /// </summary>
        /// <returns></returns>
        public async Task <IDisposable> LockReadAsync(int millisecondsTimeout = int.MaxValue)
        {
            MyLockQueueItem queueItem;
            IDisposable     answer;

            lock (_lock)
            {
                // If there's no items
                if (_queue.Count == 0)
                {
                    // Create a new read entry
                    var newEntry = new MyReadLockQueueItem(this, true);

                    // Add it to the queue
                    _queue.Add(newEntry);

                    // We're already locked, so just return instantly
                    return(new MyDisposableLock(newEntry));
                }

                // If there's only one item, and it's another read, merge with it
                if (_queue.Count == 1 && _queue[0] is MyReadLockQueueItem)
                {
                    (_queue[0] as MyReadLockQueueItem).Add();

                    // We're already locked, so just return instantly
                    return(new MyDisposableLock(_queue[0]));
                }

                // If there's a read at the end, merge with it
                else if (_queue.Last() is MyReadLockQueueItem)
                {
                    var last = _queue.Last() as MyReadLockQueueItem;
                    last.Add();

                    // Need to wait till this one starts
                    queueItem = last;
                    answer    = new MyDisposableLock(last);
                }

                // Otherwise, the last item is a write, so we need to add new and wait
                else
                {
                    var newEntry = new MyReadLockQueueItem(this, alreadyLocked: false);

                    _queue.Add(newEntry);

                    queueItem = newEntry;
                    answer    = new MyDisposableLock(newEntry);
                }
            }

            try
            {
                await TimeoutTask.Create(queueItem.LockedTask, millisecondsTimeout);
            }
            catch (TimeoutException)
            {
                queueItem.Release();
                throw new TimeoutException("Timeout exceeded and lock not established.");
            }
            return(answer);
        }