Esempio n. 1
0
        public void AsyncLock_Locked_PreventsLockUntilUnlocked()
        {
            AsyncContext.Run(async () =>
            {
                var mutex = new AsyncLock();
                var task1HasLock = new TaskCompletionSource();
                var task1Continue = new TaskCompletionSource();

                Task<IDisposable> task1LockTask = null;
                var task1 = Task.Run(async () =>
                {
                    task1LockTask = mutex.LockAsync();
                    using (await task1LockTask)
                    {
                        task1HasLock.SetResult();
                        await task1Continue.Task;
                    }
                });
                await task1HasLock.Task;

                Task<IDisposable> task2LockTask = null;
                var task2Start = Task.Factory.StartNew(async () =>
                {
                    task2LockTask = mutex.LockAsync();
                    await task2LockTask;
                });
                var task2 = await task2Start;

                Assert.IsFalse(task2.IsCompleted);
                task1Continue.SetResult();
                await task2;
            });
        }
Esempio n. 2
0
        public void AsyncLock_Locked_PreventsLockUntilUnlocked()
        {
            Test.Async(async () =>
            {
                var mutex = new AsyncLock();
                var task1HasLock = new TaskCompletionSource();
                var task1Continue = new TaskCompletionSource();

                var task1 = TaskShim.Run(async () =>
                {
                    using (await mutex.LockAsync())
                    {
                        task1HasLock.SetResult();
                        await task1Continue.Task;
                    }
                });
                await task1HasLock.Task;

                var task2Start = Task.Factory.StartNew(async () =>
                {
                    await mutex.LockAsync();
                });
                var task2 = await task2Start;

                Assert.IsFalse(task2.IsCompleted);
                task1Continue.SetResult();
                await task2;
            });
        }
        public void MultipleWaits_NotifyAll_AllAreCompleted()
        {
            AsyncContext.Run(async () =>
            {
                var mutex = new AsyncLock();
                var cv = new AsyncConditionVariable(mutex);
                var key1 = await mutex.LockAsync();
                var task1 = cv.WaitAsync();
                var __ = task1.ContinueWith(_ => key1.Dispose());
                var key2 = await mutex.LockAsync();
                var task2 = cv.WaitAsync();
                var ___ = task2.ContinueWith(_ => key2.Dispose());

                await Task.Run(async () =>
                {
                    using (await mutex.LockAsync())
                    {
                        cv.NotifyAll();
                    }
                });

                await task1;
                await task2;
            });
        }
Esempio n. 4
0
        /// <summary>
        /// Authenticates with the server and creates all the necessary components.
        /// All of them should be initialized inside the synchronized block and MUST NOT call any method on <see cref="SpotifySession">this</see> object.
        /// </summary>
        /// <param name="credentials"><see cref="Spotify.LoginCredentials"/></param>
        /// <exception cref="MercuryException"></exception>
        private async Task Authenticate(
            [NotNull] Spotify.LoginCredentials credentials,
            [NotNull] WebsocketHandler handler)
        {
            AuthenticatePartial(credentials, false);

            using (await authLock.LockAsync())
            {
                //Initialize Services
                mercuryClient = new MercuryClient(this);
                eventService  = new EventService(this);
                tokenProvider = new TokenProvider(this);
                apiClient     = await ApiClient.BuildApiClient(this);

                dealer = new DealerClient(this, handler);
                //_audioKeyManager = new AudioKeyManager(this);
                //  _channelManager = new ChannelManager(this);
                //  _cdn = new CdnManager(this);
                // _cache = new CacheManager(_inner.Conf);
                //   _contentFeeder = new PlayableContentFeeder(this);
                authLockEventWaitHandle.Set();
            }

            receiver = new Receiver(this);

            eventService.Language(inner.PreferredLocale);
            TimeProvider.Init(this);

            Debug.WriteLine($"Authenticated as {apWelcome.CanonicalUsername}!");
            Mercury().InterestedIn("spotify:user:attributes:update", this);
            Dealer().AddMessageListener(this, "hm://connect-state/v1/connect/logout");
        }
        public void WaitAsync_Notified_IsCompleted()
        {
            Test.Async(async () =>
            {
                var mutex = new AsyncLock();
                var cv = new AsyncConditionVariable(mutex);
                await mutex.LockAsync();
                var task = cv.WaitAsync();

                await TaskShim.Run(async () =>
                {
                    using (await mutex.LockAsync())
                    {
                        cv.Notify();
                    }
                });
                await task;
            });
        }
Esempio n. 6
0
        public void AsyncLock_Unlocked_SynchronouslyPermitsLock()
        {
            var mutex = new AsyncLock();

            var lockTask = mutex.LockAsync();

            Assert.IsTrue(lockTask.IsCompleted);
            Assert.IsFalse(lockTask.IsFaulted);
            Assert.IsFalse(lockTask.IsCanceled);
        }
Esempio n. 7
0
        public void AsyncLock_DoubleDispose_OnlyPermitsOneTask()
        {
            AsyncContext.Run(async () =>
            {
                var mutex = new AsyncLock();
                var task1HasLock = new TaskCompletionSource();
                var task1Continue = new TaskCompletionSource();

                Task<IDisposable> lockTask = null;
                await Task.Run(async () =>
                {
                    lockTask = mutex.LockAsync();
                    var key = await lockTask;
                    key.Dispose();
                    key.Dispose();
                });

                Task<IDisposable> task1LockTask = null;
                var task1 = Task.Run(async () =>
                {
                    task1LockTask = mutex.LockAsync();
                    using (await task1LockTask)
                    {
                        task1HasLock.SetResult();
                        await task1Continue.Task;
                    }
                });
                await task1HasLock.Task;

                Task<IDisposable> task2LockTask = null;
                var task2Start = Task.Factory.StartNew(async () =>
                {
                    task2LockTask = mutex.LockAsync();
                    await task2LockTask;
                });
                var task2 = await task2Start;

                Assert.IsFalse(task2.IsCompleted);
                task1Continue.SetResult();
                await task2;
            });
        }
        public void WaitAsync_AfterNotify_IsNotCompleted()
        {
            Test.Async(async () =>
            {
                var mutex = new AsyncLock();
                var cv = new AsyncConditionVariable(mutex);
                await TaskShim.Run(async () =>
                {
                    using (await mutex.LockAsync())
                    {
                        cv.Notify();
                    }
                });

                await mutex.LockAsync();
                var task = cv.WaitAsync();

                await AssertEx.NeverCompletesAsync(task);
            });
        }
        public void WaitAsync_WithoutNotify_IsNotCompleted()
        {
            Test.Async(async () =>
            {
                var mutex = new AsyncLock();
                var cv = new AsyncConditionVariable(mutex);

                await mutex.LockAsync();
                var task = cv.WaitAsync();

                await AssertEx.NeverCompletesAsync(task);
            });
        }
Esempio n. 10
0
        public void AsyncLock_DoubleDispose_OnlyPermitsOneTask()
        {
            Test.Async(async () =>
            {
                var mutex = new AsyncLock();
                var task1HasLock = new TaskCompletionSource();
                var task1Continue = new TaskCompletionSource();

                await TaskShim.Run(async () =>
                {
                    var key = await mutex.LockAsync();
                    key.Dispose();
                    key.Dispose();
                });

                var task1 = TaskShim.Run(async () =>
                {
                    using (await mutex.LockAsync())
                    {
                        task1HasLock.SetResult();
                        await task1Continue.Task;
                    }
                });
                await task1HasLock.Task;

                var task2Start = Task.Factory.StartNew(async () =>
                {
                    await mutex.LockAsync();
                });
                var task2 = await task2Start;

                Assert.IsFalse(task2.IsCompleted);
                task1Continue.SetResult();
                await task2;
            });
        }
Esempio n. 11
0
        /// <summary>
        /// The Lock mechanism designed for standard using blocks. This lock is thread and interprocess safe.
        /// You can create and use it from anywhere.
        /// </summary>
        /// <param name="pollInterval">The frequency of polling the termination of the mutex-thread.</param>
        /// <returns>The IDisposable await-able Task.</returns>
        public async Task <IDisposable> LockAsync(CancellationToken cancellationToken = default, int pollInterval = 100)
        {
            Exception inner = null;

            try
            {
                if (IsQuitPending)
                {
                    throw new OperationCanceledException($"{nameof(AsyncMutex)}.{nameof(AsyncMutex.LockAsync)} failed because quit is pending on: {ShortName}.");
                }

                // Local lock for thread safety.
                await AsyncLock.LockAsync(cancellationToken).ConfigureAwait(false);

                if (IsAlive)
                {
                    throw new InvalidOperationException("Thread should not be alive.");
                }

                MutexThread = new Thread(new ParameterizedThreadStart(HoldLock))
                {
                    Name = $"{nameof(MutexThread)}"
                };

                MutexThread.Start(cancellationToken);

                ChangeStatus(AsyncLockStatus.StatusAcquiring, AsyncLockStatus.StatusReady);

                // Thread is running from now.

                try
                {
                    // Create the mutex and acquire it.
                    await SetCommandAsync(1, cancellationToken, pollInterval).ConfigureAwait(false);
                }
                catch (Exception ex)
                {
                    Logger.LogWarning(ex);

                    // If the thread is still alive we must stop it
                    StopThread();

                    ChangeStatus(AsyncLockStatus.StatusReady, AsyncLockStatus.StatusAcquiring);

                    throw ex;
                }

                ChangeStatus(AsyncLockStatus.StatusAcquired, AsyncLockStatus.StatusAcquiring);

                return(new Key(this));
            }
            catch (TaskCanceledException)
            {
                // Let it go.
            }
            catch (AbandonedMutexException)
            {
                // abandoned mutexes are still acquired, we just need
                // to handle the exception and treat it as acquisition
                Logger.LogWarning($"{nameof(AbandonedMutexException)} in {ShortName}.");
                return(new Key(this));
            }
            catch (Exception ex)
            {
                Logger.LogError($"{ex.ToTypeMessageString()} in {ShortName}.");
                inner = ex;

                // Let it go.
            }

            // Release the local lock.
            AsyncLock.ReleaseLock();

            throw new IOException($"Could not acquire system wide mutex on {ShortName}.", inner);
        }
Esempio n. 12
0
        public void AsyncLock_CanceledTooLate_StillTakesLock()
        {
            AsyncContext.Run(async () =>
            {
                var mutex = new AsyncLock();
                var cts = new CancellationTokenSource();

                Task<IDisposable> initialLockTask, cancelableLockTask;
                initialLockTask = mutex.LockAsync();
                using (await initialLockTask)
                {
                    cancelableLockTask = mutex.LockAsync(cts.Token);
                }

                var key = await cancelableLockTask;
                cts.Cancel();

                var nextLocker = mutex.LockAsync();
                Assert.IsFalse(nextLocker.IsCompleted);

                key.Dispose();
                await nextLocker;
            });
        }
Esempio n. 13
0
        public void AsyncLock_CanceledLock_ThrowsException()
        {
            AsyncContext.Run(async () =>
            {
                var mutex = new AsyncLock();
                var cts = new CancellationTokenSource();

                var initialLockTask = mutex.LockAsync();
                await initialLockTask;
                var canceledLockTask = mutex.LockAsync(cts.Token);
                cts.Cancel();

                await AssertEx.ThrowsExceptionAsync<OperationCanceledException>(canceledLockTask);
            });
        }
Esempio n. 14
0
        public void AsyncLock_CancelledLock_LeavesLockUnlocked()
        {
            AsyncContext.Run(async () =>
            {
                var mutex = new AsyncLock();
                var cts = new CancellationTokenSource();
                var taskReady = new TaskCompletionSource();
                Task<IDisposable> initialLockTask = null, lockTask = null;

                initialLockTask = mutex.LockAsync();
                var unlock = await initialLockTask;
                var task = Task.Run(async () =>
                {
                    lockTask = mutex.LockAsync(cts.Token);
                    taskReady.SetResult();
                    await lockTask;
                });
                await taskReady.Task;
                cts.Cancel();
                await AssertEx.ThrowsExceptionAsync<OperationCanceledException>(task);
                Assert.IsTrue(task.IsCanceled);
                unlock.Dispose();

                var finalLockTask = mutex.LockAsync();
                await finalLockTask;
            });
        }
Esempio n. 15
0
        public void AsyncLock_PreCancelled_Locked_SynchronouslyCancels()
        {
            var mutex = new AsyncLock();
            var lockTask = mutex.LockAsync();
            var token = new CancellationToken(true);

            var task = mutex.LockAsync(token);

            Assert.IsTrue(task.IsCompleted);
            Assert.IsTrue(task.IsCanceled);
            Assert.IsFalse(task.IsFaulted);
        }
Esempio n. 16
0
        public void AsyncLock_CanceledTooLate_StillTakesLock()
        {
            Test.Async(async () =>
            {
                var mutex = new AsyncLock();
                var cts = new CancellationTokenSource();

                AwaitableDisposable<IDisposable> cancelableLockTask;
                using (await mutex.LockAsync())
                {
                    cancelableLockTask = mutex.LockAsync(cts.Token);
                }

                var key = await cancelableLockTask;
                cts.Cancel();

                var nextLocker = mutex.LockAsync().AsTask();
                Assert.IsFalse(nextLocker.IsCompleted);

                key.Dispose();
                await nextLocker;
            });
        }
Esempio n. 17
0
 /// <summary>
 /// Asynchronously enters the monitor. Returns a disposable that leaves the monitor when disposed.
 /// </summary>
 /// <param name="cancellationToken">The cancellation token used to cancel the enter. If this is already set, then this method will attempt to enter the monitor immediately (succeeding if the monitor is currently available).</param>
 /// <returns>A disposable that leaves the monitor when disposed.</returns>
 public AwaitableDisposable <IDisposable> EnterAsync(CancellationToken cancellationToken)
 {
     return(_asyncLock.LockAsync(cancellationToken));
 }
        public void MultipleWaits_Notify_OneIsCompleted()
        {
            Test.Async(async () =>
            {
                var mutex = new AsyncLock();
                var cv = new AsyncConditionVariable(mutex);
                var key = await mutex.LockAsync();
                var task1 = cv.WaitAsync();
                var __ = task1.ContinueWith(_ => key.Dispose());
                await mutex.LockAsync();
                var task2 = cv.WaitAsync();

                await TaskShim.Run(async () =>
                {
                    using (await mutex.LockAsync())
                    {
                        cv.Notify();
                    }
                });

                await task1;
                await AssertEx.NeverCompletesAsync(task2);
            });
        }
Esempio n. 19
0
        public void AsyncLock_Locked_OnlyPermitsOneLockerAtATime()
        {
            Test.Async(async () =>
            {
                var mutex = new AsyncLock();
                var task1HasLock = new TaskCompletionSource();
                var task1Continue = new TaskCompletionSource();
                var task2HasLock = new TaskCompletionSource();
                var task2Continue = new TaskCompletionSource();

                var task1 = TaskShim.Run(async () =>
                {
                    using (await mutex.LockAsync())
                    {
                        task1HasLock.SetResult();
                        await task1Continue.Task;
                    }
                });
                await task1HasLock.Task;

                var task2Start = Task.Factory.StartNew(async () =>
                {
                    using (await mutex.LockAsync())
                    {
                        task2HasLock.SetResult();
                        await task2Continue.Task;
                    }
                });
                var task2 = await task2Start;

                var task3Start = Task.Factory.StartNew(async () =>
                {
                    await mutex.LockAsync();
                });
                var task3 = await task3Start;

                task1Continue.SetResult();
                await task2HasLock.Task;

                Assert.IsFalse(task3.IsCompleted);
                task2Continue.SetResult();
                await task2;
                await task3;
            });
        }
Esempio n. 20
0
        public void AsyncLock_Locked_OnlyPermitsOneLockerAtATime()
        {
            AsyncContext.Run(async () =>
            {
                var mutex = new AsyncLock();
                var task1HasLock = new TaskCompletionSource();
                var task1Continue = new TaskCompletionSource();
                var task2HasLock = new TaskCompletionSource();
                var task2Continue = new TaskCompletionSource();
                Task<IDisposable> task1LockTask = null, task2LockTask = null, task3LockTask = null;

                var task1 = Task.Run(async () =>
                {
                    task1LockTask = mutex.LockAsync();
                    using (await task1LockTask)
                    {
                        task1HasLock.SetResult();
                        await task1Continue.Task;
                    }
                });
                await task1HasLock.Task;

                var task2Start = Task.Factory.StartNew(async () =>
                {
                    task2LockTask = mutex.LockAsync();
                    using (await task2LockTask)
                    {
                        task2HasLock.SetResult();
                        await task2Continue.Task;
                    }
                });
                var task2 = await task2Start;

                var task3Start = Task.Factory.StartNew(async () =>
                {
                    task3LockTask = mutex.LockAsync();
                    await task3LockTask;
                });
                var task3 = await task3Start;

                task1Continue.SetResult();
                await task2HasLock.Task;

                Assert.IsFalse(task3.IsCompleted);
                task2Continue.SetResult();
                await task2;
                await task3;
            });
        }
        public async Task AsyncLock_DoesNotPermitRecursiveWaits()
        {
            var mutex = new AsyncLock();
            var key = await mutex.LockAsync();
            
            var waiter = mutex.LockAsync().AsTask();

            Assert.IsFalse(waiter.Wait(1000));
            key.Dispose();
        }
Esempio n. 22
0
        public void AsyncLock_CanceledLock_ThrowsException()
        {
            Test.Async(async () =>
            {
                var mutex = new AsyncLock();
                var cts = new CancellationTokenSource();

                await mutex.LockAsync();
                var canceledLockTask = mutex.LockAsync(cts.Token).AsTask();
                cts.Cancel();

                await AssertEx.ThrowsExceptionAsync<OperationCanceledException>(canceledLockTask);
            });
        }