BinaryAsyncLock is a helper primitive that can be used instead of SemaphoreSlim.WaitAsync + double-checked locking
After BinaryAsyncLock is created or reset, the first caller of WaitAsync will immediately get IBinaryAsyncLockToken that is not set. All other callers will either wait until IBinaryAsyncLockToken.Set is called and then will get , or until until IBinaryAsyncLockToken.Reset is called and next awaiting caller will get ,
        public async Task WaitAsync_SetInCtor() {
            var bal = new BinaryAsyncLock(true);
            var count = 0;
            await ParallelTools.InvokeAsync(4, async i => {
                await bal.WaitAsync();
                if (!bal.IsSet) {
                    await Task.Delay(50);
                    Interlocked.Increment(ref count);
                }
            });

            count.Should().Be(0);
        }
        public async Task WaitAsync_Reset() {
            var bal = new BinaryAsyncLock();
            var count = 0;
            await ParallelTools.InvokeAsync(4, async i => {
                var token = await bal.WaitAsync();
                if (!bal.IsSet) {
                    await Task.Delay(50);
                    Interlocked.Increment(ref count);
                    token.Reset();
                }
            });

            count.Should().Be(4);
        }
        public RPackageManagerViewModel(IRPackageManager packageManager, IRSettings settings, ICoreShell coreShell) {
            _packageManager = packageManager;
            _settings = settings;
            _coreShell = coreShell;
            _selectedTab = Tab.None;
            _availablePackages = new List<IRPackageViewModel>();
            _installedPackages = new List<IRPackageViewModel>();
            _loadedPackages = new List<IRPackageViewModel>();
            _availableLock = new BinaryAsyncLock();
            _installedAndLoadedLock = new BinaryAsyncLock();
            _items = new BatchObservableCollection<object>();
            _errorMessages = new ErrorMessageCollection(this);
            Items = new ReadOnlyObservableCollection<object>(_items);

            _packageManager.AvailablePackagesInvalidated += AvailablePackagesInvalidated;
            _packageManager.InstalledPackagesInvalidated += InstalledPackagesInvalidated;
            _packageManager.LoadedPackagesInvalidated += LoadedPackagesInvalidated;
        }
        public void ResetIfNotWaiting_ResetAsync_Skip_WaitAsync_Set() {
            var bal = new BinaryAsyncLock();
            var task = bal.ResetAsync();

            task.Should().BeRanToCompletion();
            bal.IsSet.Should().BeFalse();

            task.Result.Reset();

            bal.IsSet.Should().BeFalse();

            task = bal.WaitAsync();

            task.Should().BeRanToCompletion();
            bal.IsSet.Should().BeFalse();

            task.Result.Set();

            bal.IsSet.Should().BeTrue();
        }
Exemple #5
0
 public TokenSource(BinaryAsyncLock binaryAsyncLock) {
     Task = System.Threading.Tasks.Task.FromResult<IBinaryAsyncLockToken>(new Token(binaryAsyncLock, this));
 }
Exemple #6
0
 public Token(BinaryAsyncLock binaryAsyncLock, TokenSource tokenSource) {
     _binaryAsyncLock = binaryAsyncLock;
     _tokenSource = tokenSource;
     IsSet = false;
 }
Exemple #7
0
 public TokenSource(BinaryAsyncLock binaryAsyncLock)
 {
     Task = System.Threading.Tasks.Task.FromResult <IBinaryAsyncLockToken>(new Token(binaryAsyncLock, this));
 }
Exemple #8
0
 public Token(BinaryAsyncLock binaryAsyncLock, TokenSource tokenSource)
 {
     _binaryAsyncLock = binaryAsyncLock;
     _tokenSource     = tokenSource;
     IsSet            = false;
 }
        public void WaitAsync_ResetAsync_Set() {
            var bal = new BinaryAsyncLock();
            var task1 = bal.WaitAsync();
            var task2 = bal.ResetAsync();

            task1.Result.Set();

            task1.Should().BeRanToCompletion();
            task2.Should().BeRanToCompletion();
            bal.IsSet.Should().BeFalse();
        }
Exemple #10
0
        public void CancelEven() {
            var bal = new BinaryAsyncLock(true);
            var cts = new CancellationTokenSource();
            var task1 = bal.ResetAsync();
            var task2 = bal.ResetAsync(cts.Token);
            var task3 = bal.ResetAsync(cts.Token);
            var task4 = bal.WaitAsync();
            var task5 = bal.WaitAsync(cts.Token);

            task1.Should().BeRanToCompletion();
            task2.Should().NotBeCompleted();
            task3.Should().NotBeCompleted();
            task4.Should().NotBeCompleted();
            task5.Should().NotBeCompleted();

            cts.Cancel();
            task1.Should().BeRanToCompletion();
            task2.Should().BeCanceled();
            task3.Should().BeCanceled();
            task4.Should().NotBeCompleted();
            task5.Should().BeCanceled();

            task1.Result.Reset();
            task1.Should().BeRanToCompletion();
            task2.Should().BeCanceled();
            task3.Should().BeCanceled();
            task4.Should().BeRanToCompletion();
            task5.Should().BeCanceled();

            bal.IsSet.Should().BeFalse();
        }
Exemple #11
0
        public void CancelResetAsync_Set() {
            var bal = new BinaryAsyncLock(true);
            var cts = new CancellationTokenSource();
            var tasks = Enumerable.Range(0, 4).Select(i => bal.ResetAsync(cts.Token)).ToList();
            tasks.Should().ContainSingle(t => t.IsCompleted);

            cts.Cancel();
            tasks.Should().OnlyContain(t => t.IsCompleted);
        }
Exemple #12
0
        public void CancelWaitAsync_Set() {
            var bal = new BinaryAsyncLock(true);
            var cts = new CancellationTokenSource();
            var tasks = Enumerable.Range(0, 4).Select(i => bal.WaitAsync(cts.Token)).ToList();
            tasks.Should().OnlyContain(t => t.Status == TaskStatus.RanToCompletion);

            cts.Cancel();
            tasks.Should().OnlyContain(t => t.Status == TaskStatus.RanToCompletion);
        }
Exemple #13
0
        public void SequentalWaitReset_SetToken() {
            var bal = new BinaryAsyncLock(true);
            var task1 = bal.ResetAsync();
            var task2 = bal.WaitAsync();
            var task3 = bal.ResetAsync();
            var task4 = bal.WaitAsync();
            var task5 = bal.ResetAsync();

            task1.Should().BeRanToCompletion();
            task2.Should().NotBeCompleted();
            task3.Should().NotBeCompleted();
            task4.Should().NotBeCompleted();
            task5.Should().NotBeCompleted();
            bal.IsSet.Should().BeFalse();

            task1.Result.Set();

            task1.Should().BeRanToCompletion();
            task2.Should().BeRanToCompletion();
            task3.Should().BeRanToCompletion();
            task4.Should().NotBeCompleted();
            task5.Should().NotBeCompleted();
            bal.IsSet.Should().BeFalse();

            task3.Result.Set();

            task1.Should().BeRanToCompletion();
            task2.Should().BeRanToCompletion();
            task3.Should().BeRanToCompletion();
            task4.Should().BeRanToCompletion();
            task5.Should().BeRanToCompletion();
            bal.IsSet.Should().BeFalse();
        }
Exemple #14
0
        public void ResetAsync_ResetAsync_WaitAsync_CancelSecond_SetFirst() {
            var bal = new BinaryAsyncLock(true);
            var cts = new CancellationTokenSource();

            var task1 = bal.ResetAsync();
            var task2 = bal.ResetAsync(cts.Token);
            var task3 = bal.WaitAsync();

            cts.Cancel();
            task1.Result.Set();

            task1.Should().BeRanToCompletion();
            task2.Should().BeCanceled();
            task3.Should().BeRanToCompletion();
            bal.IsSet.Should().BeTrue();
        }
Exemple #15
0
        public void ResetAsync_ResetAsync_Set_SetIfLast() {
            var bal = new BinaryAsyncLock();
            var task1 = bal.ResetAsync();
            var task2 = bal.ResetAsync();

            task1.Result.Set();
            task2.Result.SetIfLast();

            task1.Should().BeRanToCompletion();
            task2.Should().BeRanToCompletion();
            bal.IsSet.Should().BeTrue();
        }