예제 #1
0
        public Task <IAsyncReaderWriterLockToken> WriterLockAsync(CancellationToken cancellationToken = default(CancellationToken), ReentrancyToken reentrancyToken = default(ReentrancyToken))
        {
            TaskUtilities.AssertIsOnBackgroundThread();

            var task = ReentrantOrCanceled(true, cancellationToken, reentrancyToken);

            if (task != null)
            {
                return(task);
            }

            var source = new LockSource(this, true);

            _queue.AddWriter(source, out var isFirstWriter);
            if (isFirstWriter)
            {
                source.Release();
            }
            else
            {
                source.RegisterCancellation(cancellationToken);
            }

            return(source.Task);
        }
예제 #2
0
 static AsyncReaderWriterLock()
 {
     LockTokenFactory = ReentrancyToken.CreateFactory <LockSource>();
 }
예제 #3
0
        private static Task <IAsyncReaderWriterLockToken> ReentrantOrCanceled(bool writerOnly, CancellationToken cancellationToken, ReentrancyToken reentrancyToken)
        {
            var source = LockTokenFactory.GetSource(reentrancyToken);

            if (source != null && source.TryReenter(writerOnly, out var task))
            {
                return(task);
            }

            return(cancellationToken.IsCancellationRequested ? Task.FromCanceled <IAsyncReaderWriterLockToken>(cancellationToken) : null);
        }
예제 #4
0
        public Task <IAsyncReaderWriterLockToken> WriterLockAsync(CancellationToken cancellationToken = default(CancellationToken), ReentrancyToken reentrancyToken = default(ReentrancyToken))
        {
            Task <IAsyncReaderWriterLockToken> task;
            var writerFromToken = WriterLockTokenFactory.GetSource(reentrancyToken);

            if (writerFromToken != null && writerFromToken.TryReenter(out task))
            {
                return(task);
            }

            while (true)
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    return(Task.FromCanceled <IAsyncReaderWriterLockToken>(cancellationToken));
                }

                WriterLockSource oldWriter = _writerTail;
                WriterLockSource newWriter;
                if (!oldWriter.TrySetNext(out newWriter))
                {
                    continue;
                }

                var reader = oldWriter.IsCompleted && _lastAcquiredWriter == oldWriter
                    ? Interlocked.Exchange(ref _readerTail, new ReaderLockSource(this))
                    : null;

                if (Interlocked.CompareExchange(ref _writerTail, newWriter, oldWriter) != oldWriter)
                {
                    throw new InvalidOperationException();
                }

                if (reader != null)   // oldWriter.IsCompleted
                {
                    reader.RegisterWait(newWriter, cancellationToken);
                }
                else
                {
                    oldWriter.RegisterWait(cancellationToken);
                }

                return(newWriter.Task);
            }
        }
예제 #5
0
        public Task <IAsyncReaderWriterLockToken> ReaderLockAsync(CancellationToken cancellationToken = default(CancellationToken), ReentrancyToken reentrancyToken = default(ReentrancyToken))
        {
            Task <IAsyncReaderWriterLockToken> task;
            var writerFromToken = WriterLockTokenFactory.GetSource(reentrancyToken);

            if (writerFromToken != null && writerFromToken.TryReenter(out task))
            {
                return(task);
            }

            var readerFromToken = ReaderLockTokenFactory.GetSource(reentrancyToken);

            if (readerFromToken != null && readerFromToken.TryReenter(out task))
            {
                return(task);
            }

            while (true)
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    return(Task.FromCanceled <IAsyncReaderWriterLockToken>(cancellationToken));
                }

                task = _readerTail.WaitAsync(cancellationToken);
                if (task != null)
                {
                    return(task);
                }
            }
        }
예제 #6
0
 public Token(Action dispose, ReaderLockSource reentrancySource)
 {
     _dispose   = dispose;
     Reentrancy = ReaderLockTokenFactory.Create(reentrancySource);
 }