private async Task StartAsyncCore(CancellationToken cancellationToken)
 {
     ListenerFactoryContext context = new ListenerFactoryContext(cancellationToken);
     _listener = await _factory.CreateAsync(context);
     _cancellationRegistration = _cancellationSource.Token.Register(_listener.Cancel);
     await _listener.StartAsync(cancellationToken);
 }
Exemple #2
0
        /// <summary>
        /// If AutoSaveChanges is set this method will auto commit changes
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        protected virtual Task<int> SaveChanges(CancellationToken cancellationToken)
        {
            var source = new TaskCompletionSource<int>();
            if (AutoSaveChanges) {
                var registration = new CancellationTokenRegistration();
                if (cancellationToken.CanBeCanceled) {
                    if (cancellationToken.IsCancellationRequested) {
                        source.SetCanceled();
                        return source.Task;
                    }
                    registration = cancellationToken.Register(CancelIgnoreFailure);
                }

                try
                {
                    return _uow.SaveChangesAsync(cancellationToken);
                }
                catch (Exception e)
                {
                    source.SetException(e);
                }
                finally
                {
                    registration.Dispose();
                }
            }
            return source.Task;
        }
        public void DefaultCancellationTokenRegistration()
        {
            var registration = new CancellationTokenRegistration ();

            // shouldn't throw
            registration.Dispose ();
        }
 protected ScheduledAsyncTask(AbstractScheduledEventExecutor executor, PreciseDeadline deadline,
     TaskCompletionSource promise, CancellationToken cancellationToken)
     : base(executor, deadline, promise)
 {
     _cancellationToken = cancellationToken;
     _cancellationTokenRegistration = cancellationToken.Register(CancellationAction, this);
 }
Exemple #5
0
        internal IrcNetworkStream(IIrcClient client)
        {   
            _streamReader = new StreamReader(client.GetClientStream());
            _streamWriter = new StreamWriter(client.GetClientStream());

            _cancellationRegistration = _cancellationToken.Register(TaskRequestErrorCallback);
        }
        public RSessionRequestSource(bool isVisible, CancellationToken ct) {
            _createRequestTcs = new TaskCompletionSourceEx<IRSessionInteraction>();
            _responseTcs = new TaskCompletionSourceEx<object>();
            _cancellationTokenRegistration = ct.Register(() => _createRequestTcs.TrySetCanceled(cancellationToken:ct));

            IsVisible = isVisible;
        }
Exemple #7
0
        internal SchedulerOperationAwaiter(Func<Action, IDisposable> schedule, CancellationToken cancellationToken, bool postBackToOriginalContext)
        {
            _schedule = schedule;
            _cancellationToken = cancellationToken;
            _postBackToOriginalContext = postBackToOriginalContext;

            _ctr = _cancellationToken.Register(Cancel);
        }
 public Http2ClientStream(int id, Priority priority, WriteQueue writeQueue, HeaderWriter headerWriter, CancellationToken cancel)
     : base(id, writeQueue, headerWriter, cancel)
 {
     _priority = priority;
     _responseTask = new TaskCompletionSource<IList<KeyValuePair<string, string>>>();
     _outputStream = new OutputStream(id, _priority, writeQueue);
     _cancellation = _cancel.Register(Cancel, this);
 }
        public void TypePropertiesForCancellationTokenRegistrationAreCorrect()
        {
            Assert.AreEqual(typeof(CancellationTokenRegistration).GetClassName(), "Bridge.CancellationTokenRegistration", "FullName");

            object ctr = new CancellationTokenRegistration();
            Assert.True(ctr is CancellationTokenRegistration, "CancellationTokenRegistration");
            Assert.True(ctr is IDisposable, "IDisposable");
            Assert.True(ctr is IEquatable<CancellationTokenRegistration>, "IEquatable<CancellationTokenRegistration>");
        }
        internal VerifierDialog(MainWindow parentWindow)
            : base(parentWindow, null)
        {
            InitializeComponent();

            this.m_mainwindow = parentWindow;

            this.m_tcs = new TaskCompletionSource<object>();
            this.m_cancel = DialogSettings.CancellationToken.Register(() => this.m_tcs.TrySetResult(null));
        }
        internal ClientSelectionDialog(MetroWindow parentWindow)
            : base(parentWindow, null)
        {
            InitializeComponent();

            this.ctlList.ItemsSource = SongInfo.LastResult;

            this.m_tcs = new TaskCompletionSource<object>();
            this.m_cancel = DialogSettings.CancellationToken.Register(() => this.m_tcs.TrySetResult(null));
        }
        internal ADSelectionDialog(MetroWindow parentWindow)
            : base(parentWindow, null)
        {
            InitializeComponent();

            this.ctlList.ItemsSource = IParseRule.RulesPlayer;

            this.m_tcs = new TaskCompletionSource<object>();
            this.m_cancel = DialogSettings.CancellationToken.Register(() => this.m_tcs.TrySetResult(null));
        }
		public Task RunAsync(IEnumerable<ITest> selectedTests, IProgress<double> progress, TextWriter output, CancellationToken cancellationToken)
		{
			this.progress = progress;
			this.output = output;
			progressPerTest = 1.0 / GetExpectedNumberOfTestResults(selectedTests);
			tcs = new TaskCompletionSource<object>();
			Start(selectedTests);
			cancellationTokenRegistration = cancellationToken.Register(Cancel, true);
			return tcs.Task;
		}
Exemple #14
0
        public StopSignal()
        {
            _stopRequested = new TaskCompletionSource<bool>();

            _stopToken = new CancellationTokenSource();
            _registration = _stopToken.Token.Register(() =>
            {
                _stopRequested.TrySetResult(true);

                _registration.Dispose();
            });
        }
			public void RunJob(BuildJob job, IMSBuildChainedLoggerFilter loggerChain, Action<bool> reportWhenDone, CancellationToken cancellationToken)
			{
				Debug.Assert(loggerChain != null);
				this.loggerChain = loggerChain;
				this.reportWhenDone = reportWhenDone;
				try {
					process.Writer.Write("StartBuild");
					job.WriteTo(process.Writer);
					this.cancellationRegistration = cancellationToken.Register(OnCancel);
				} catch (IOException ex) {
					// "Pipe is broken"
					loggerChain.HandleError(new BuildError(null, 0, 0, null, "Error talking to build worker: " + ex.Message));
					BuildDone(false);
				}
			}
        public RabbitMqBasicConsumer(ModelContext model, Uri inputAddress, IPipe<ReceiveContext> receivePipe, IReceiveObserver receiveObserver,
            CancellationToken cancellationToken)
        {
            _model = model;
            _inputAddress = inputAddress;
            _receivePipe = receivePipe;
            _receiveObserver = receiveObserver;

            _receiveSettings = model.GetPayload<ReceiveSettings>();

            _pending = new ConcurrentDictionary<ulong, RabbitMqReceiveContext>();

            _consumerComplete = new TaskCompletionSource<RabbitMqConsumerMetrics>();

            _registration = cancellationToken.Register(Complete);
        }
        // Similar to TaskFactory.FromAsync, except it supports cancellation using ICancellableAsyncResult.
        public static Task FromAsync(Func<AsyncCallback, object, ICancellableAsyncResult> beginMethod,
            Action<IAsyncResult> endMethod, CancellationToken cancellationToken)
        {
            TaskCompletionSource<object> source = new TaskCompletionSource<object>();

            CancellationTokenRegistration cancellationRegistration = new CancellationTokenRegistration();
            bool cancellationRegistrationDisposed = false;
            object cancellationRegistrationLock = new object();

            ICancellableAsyncResult result = beginMethod.Invoke((ar) =>
            {
                lock (cancellationRegistrationLock)
                {
                    cancellationRegistration.Dispose();
                    cancellationRegistrationDisposed = true;
                }

                try
                {
                    endMethod.Invoke(ar);
                    source.SetResult(null);
                }
                catch (OperationCanceledException)
                {
                    source.SetCanceled();
                }
                catch (Exception exception)
                {
                    source.SetException(exception);
                }
            }, null);

            lock (cancellationRegistrationLock)
            {
                if (!cancellationRegistrationDisposed)
                {
                    cancellationRegistration = cancellationToken.Register(result.Cancel);
                }
            }

            if (result.CompletedSynchronously)
            {
                System.Diagnostics.Debug.Assert(source.Task.IsCompleted);
            }

            return source.Task;
        }
            public OpenSession(EsentStorage storage, string databaseFile, CancellationToken shutdownCancellationToken)
            {
                _storage = storage;

#if false
                id = Interlocked.Increment(ref globalId);
                System.Diagnostics.Trace.WriteLine("open sessionId: " + id);
#endif

                _session = new Session(storage._instance);

                _databaseFile = databaseFile;
                _databaseId = OpenExistingDatabase(_session, databaseFile);

                _shutdownCancellationToken = shutdownCancellationToken;
                _cancellationTokenRegistration = shutdownCancellationToken.Register(() => Dispose(), useSynchronizationContext: false);
            }
        /// <summary>
        /// Creates new threadpool with given settings and cancel token values
        /// </summary>
        /// <param name="settings">thread pool runtime settings</param>
        /// <param name="cancelToken">cancel token to indicate or send stop event to the pool</param>
        public CustomThreadPool3(ThreadPoolSettings settings, CancellationToken cancelToken)
            : base(settings, cancelToken)
        {
            _settings = settings;
            _linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cancelToken);
            this._poolStopToken = _linkedCts.Token;
            _tokenRegister = _poolStopToken.Register(OnPoolCancelRequested);

            //start minimum required threads immediately
            _mThreads = new Thread[_settings.MaxThreads];
            _mThreadLocalQueues = new ThreadLocalStealQueue<ThreadPoolWorkItem>[_settings.MaxThreads];

            for (int i = 0; i < _settings.MinThreads; i++)
            {
                StartNewThread(true);
            }

            EtwLogger.Log.PoolStarted(Name, _settings.MinThreads, _settings.MaxThreads);
        }
        /// <summary>
        /// Construct socket and open connection to a specified server.
        /// </summary>
        /// <param name="log">Logging facility for verbose messaging of actions.</param>
        /// <param name="endpoint">The IP endpoint to connect to.</param>
        /// <param name="maximumReconnectionTimeout">The maximum time to wait when backing off on reconnection attempts.</param>
        public KafkaTcpSocket(IKafkaLog log, KafkaEndpoint endpoint, TimeSpan? maximumReconnectionTimeout = null)
        {
            _log = log;
            _endpoint = endpoint;
            _maximumReconnectionTimeout = maximumReconnectionTimeout ?? TimeSpan.FromMinutes(MaxReconnectionTimeoutMinutes);

            _sendTaskQueue = new AsyncCollection<SocketPayloadSendTask>();
            _readTaskQueue = new AsyncCollection<SocketPayloadReadTask>();

            //dedicate a long running task to the read/write operations
            _socketTask = Task.Run(async () => { await DedicatedSocketTask(); });

            _disposeTask = _disposeToken.Token.CreateTask();
            _disposeRegistration = _disposeToken.Token.Register(() =>
            {
                _sendTaskQueue.CompleteAdding();
                _readTaskQueue.CompleteAdding();
            });
        }
        public void AllowCancellation(SafeHandle handle, NativeOverlapped* overlapped) {
            Contract.Assert(handle != null, "Handle cannot be null");
            Contract.Assert(!handle.IsInvalid, "Handle cannot be invalid");
            Contract.Assert(overlapped != null, "Overlapped cannot be null");
            Contract.Assert(this._handle == null && this._overlapped == null, "Cancellation is already allowed.");

            if (!_cancellationToken.CanBeCanceled) {
                return;
            }

            this._handle = handle;
            this._overlapped = overlapped;
            if (this._cancellationToken.IsCancellationRequested) {
                this.Cancel();
            }
            else {
                this._cancellationRegistration = this._cancellationToken.Register(Cancel);
            }
        }
Exemple #22
0
        /// <summary>
        /// Construct socket and open connection to a specified server.
        /// </summary>
        /// <param name="log">Logging facility for verbose messaging of actions.</param>
        /// <param name="endpoint">The IP endpoint to connect to.</param>
        /// <param name="maximumReconnectionTimeout">The maximum time to wait when backing off on reconnection attempts.</param>
        public KafkaTcpSocket(IKafkaLog log, KafkaEndpoint endpoint, TimeSpan? maximumReconnectionTimeout = null)
        {
            _log = log;
            _endpoint = endpoint;
            _maximumReconnectionTimeout = maximumReconnectionTimeout ?? TimeSpan.FromMinutes(MaxReconnectionTimeoutMinutes);

            _sendTaskQueue = new AsyncCollection<SocketPayloadSendTask>();
            _readTaskQueue = new AsyncCollection<SocketPayloadReadTask>();

            //dedicate a long running task to the read/write operations
            _socketTask = Task.Factory.StartNew(DedicatedSocketTask, CancellationToken.None,
                TaskCreationOptions.LongRunning, TaskScheduler.Default);

            _disposeRegistration = _disposeToken.Token.Register(() =>
            {
                _sendTaskQueue.CompleteAdding();
                _readTaskQueue.CompleteAdding();
            });

        }
        protected TransferControllerBase(TransferScheduler transferScheduler, TransferJob transferJob, CancellationToken userCancellationToken)
        {
            if (null == transferScheduler)
            {
                throw new ArgumentNullException("transferScheduler");
            }

            if (null == transferJob)
            {
                throw new ArgumentNullException("transferJob");
            }

            this.Scheduler = transferScheduler;
            this.TransferJob = transferJob;

            this.transferSchedulerCancellationTokenRegistration =
                this.Scheduler.CancellationTokenSource.Token.Register(this.CancelWork);

            this.userCancellationTokenRegistration = userCancellationToken.Register(this.CancelWork);
            this.TaskCompletionSource = new TaskCompletionSource<object>();
        }
        public CustomThreadPool2(ThreadPoolSettings settings, CancellationToken cancelToken)
            : base(settings, cancelToken)
        {
            if (settings == null) throw new ArgumentNullException("settings");

            this._settings = settings;
            _workerKeys = new List<string>(settings.MaxThreads);

            //initialize min threads immediately
            for (int i = 0; i < settings.MinThreads; i++)
            {
                var w = AllocDelegate();
                w.IsPermenant = true;
                _workerThreads.TryAdd(w.Name, w);
                _workerKeys.Add(w.Name);
            }

            _linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cancelToken);
            this._poolStopToken = _linkedCts.Token;
            _tokenRegister = _poolStopToken.Register(OnPoolCancelRequested);
            EtwLogger.Log.PoolStarted(Name, _settings.MinThreads, _settings.MaxThreads);
        }
Exemple #25
0
        public static Task Delay(int dueTimeMs, CancellationToken cancellationToken)
        {
            if (dueTimeMs < -1) throw new ArgumentOutOfRangeException("dueTimeMs", "Invalid due time");
            if (cancellationToken.IsCancellationRequested) return preCanceledTask;
            if (dueTimeMs == 0) return preCompletedTask;

            var tcs = new TaskCompletionSource<object>();
            var ctr = new CancellationTokenRegistration();
            var timer = new Timer(self =>
            {
                ctr.Dispose();
                ((Timer) self).Dispose();
                tcs.TrySetResult(null);
            });
            if (cancellationToken.CanBeCanceled)
                ctr = cancellationToken.Register(() =>
                {
                    timer.Dispose();
                    tcs.TrySetCanceled();
                });
            timer.Change(dueTimeMs, -1);
            return tcs.Task;
        }
Exemple #26
0
        public Receiver(MessageReceiver messageReceiver, Uri inputAddress, IPipe<ReceiveContext> receivePipe,
            ReceiveSettings receiveSettings, IReceiveObserver receiveObserver, CancellationToken cancellationToken)
        {
            _messageReceiver = messageReceiver;
            _inputAddress = inputAddress;
            _receivePipe = receivePipe;
            _receiveSettings = receiveSettings;
            _receiveObserver = receiveObserver;

            _completeTask = new TaskCompletionSource<ReceiverMetrics>();

            _registration = cancellationToken.Register(Shutdown);

            var options = new OnMessageOptions
            {
                AutoComplete = false,
                AutoRenewTimeout = receiveSettings.AutoRenewTimeout,
                MaxConcurrentCalls = receiveSettings.MaxConcurrentCalls,
            };

            options.ExceptionReceived += (sender, x) => _completeTask.TrySetException(x.Exception);

            messageReceiver.OnMessageAsync(OnMessage, options);
        }
        public virtual Task<object> ExecuteScalarAsync(CancellationToken cancellationToken) {
            if (cancellationToken.IsCancellationRequested) {
                return ADP.CreatedTaskWithCancellation<object>();
            }
            else {
                CancellationTokenRegistration registration = new CancellationTokenRegistration();
                if (cancellationToken.CanBeCanceled) {
                    registration = cancellationToken.Register(CancelIgnoreFailure);
                }

                try {
                    return Task.FromResult<object>(ExecuteScalar());
                }
                catch (Exception e) {
                    registration.Dispose();
                    return ADP.CreatedTaskWithException<object>(e);
                }
            }
        }
        protected virtual Task<DbDataReader> ExecuteDbDataReaderAsync(CommandBehavior behavior, CancellationToken cancellationToken) {
            if (cancellationToken.IsCancellationRequested) {
                return ADP.CreatedTaskWithCancellation<DbDataReader>();
            }
            else {
                CancellationTokenRegistration registration = new CancellationTokenRegistration();
                if (cancellationToken.CanBeCanceled) {
                    registration = cancellationToken.Register(CancelIgnoreFailure);
                }

                try {
                    return Task.FromResult<DbDataReader>(ExecuteReader(behavior));
                }
                catch (Exception e) {
                    registration.Dispose();
                    return ADP.CreatedTaskWithException<DbDataReader>(e);
                }
            }
        }
            private void DeactivateActiveRequest(
                SafeCurlMultiHandle multiHandle, EasyRequest easy, 
                IntPtr gcHandlePtr, CancellationTokenRegistration cancellationRegistration)
            {
                // Remove the operation from the multi handle so we can shut down the multi handle cleanly
                int removeResult = Interop.libcurl.curl_multi_remove_handle(multiHandle, easy._easyHandle);
                Debug.Assert(removeResult == CURLMcode.CURLM_OK, "Failed to remove easy handle"); // ignore cleanup errors in release

                // Release the associated GCHandle so that it's not kept alive forever
                if (gcHandlePtr != IntPtr.Zero)
                {
                    try
                    {
                        GCHandle.FromIntPtr(gcHandlePtr).Free();
                        _activeOperations.Remove(gcHandlePtr);
                    }
                    catch (InvalidOperationException)
                    {
                        Debug.Fail("Couldn't get/free the GCHandle for an active operation while shutting down due to failure");
                    }
                }

                // Undo cancellation registration
                cancellationRegistration.Dispose();
            }
		CancellationTokenRegistration GetTokenReg ()
		{
			CancellationTokenRegistration registration
				= new CancellationTokenRegistration (Interlocked.Increment (ref currId), this);
			
			return registration;
		}
        /// <summary>
        /// Blocks the current thread until it can enter the <see cref="SemaphoreSlim"/>,
        /// using a 32-bit signed integer to measure the time interval,
        /// while observing a <see cref="T:System.Threading.CancellationToken"/>.
        /// </summary>
        /// <param name="millisecondsTimeout">The number of milliseconds to wait, or <see cref="Timeout.Infinite"/>(-1) to
        /// wait indefinitely.</param>
        /// <param name="cancellationToken">The <see cref="T:System.Threading.CancellationToken"/> to observe.</param>
        /// <returns>true if the current thread successfully entered the <see cref="SemaphoreSlim"/>; otherwise, false.</returns>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="millisecondsTimeout"/> is a negative number other than -1,
        /// which represents an infinite time-out.</exception>
        /// <exception cref="System.OperationCanceledException"><paramref name="cancellationToken"/> was canceled.</exception>
        public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken)
        {
            CheckDispose();

            // Validate input
            if (millisecondsTimeout < -1)
            {
                throw new ArgumentOutOfRangeException(
                          "totalMilliSeconds", millisecondsTimeout, SR.SemaphoreSlim_Wait_TimeoutWrong);
            }

            cancellationToken.ThrowIfCancellationRequested();

            uint startTime = 0;

            if (millisecondsTimeout != Timeout.Infinite && millisecondsTimeout > 0)
            {
                startTime = TimeoutHelper.GetTime();
            }

            bool        waitSuccessful = false;
            Task <bool> asyncWaitTask  = null;
            bool        lockTaken      = false;

            //Register for cancellation outside of the main lock.
            //NOTE: Register/deregister inside the lock can deadlock as different lock acquisition orders could
            //      occur for (1)this.m_lockObj and (2)cts.internalLock
            CancellationTokenRegistration cancellationTokenRegistration = cancellationToken.InternalRegisterWithoutEC(s_cancellationTokenCanceledEventHandler, this);

            try
            {
                // Perf: first spin wait for the count to be positive, but only up to the first planned yield.
                //       This additional amount of spinwaiting in addition
                //       to Monitor.Enter()’s spinwaiting has shown measurable perf gains in test scenarios.
                //
                SpinWait spin = new SpinWait();
                while (m_currentCount == 0 && !spin.NextSpinWillYield)
                {
                    spin.SpinOnce();
                }
                // entering the lock and incrementing waiters must not suffer a thread-abort, else we cannot
                // clean up m_waitCount correctly, which may lead to deadlock due to non-woken waiters.
                try { }
                finally
                {
                    Monitor.Enter(m_lock, ref lockTaken);
                    if (lockTaken)
                    {
                        m_waitCount++;
                    }
                }

                // If there are any async waiters, for fairness we'll get in line behind
                // then by translating our synchronous wait into an asynchronous one that we
                // then block on (once we've released the lock).
                if (m_asyncHead != null)
                {
                    Contract.Assert(m_asyncTail != null, "tail should not be null if head isn't");
                    asyncWaitTask = WaitAsync(millisecondsTimeout, cancellationToken);
                }
                // There are no async waiters, so we can proceed with normal synchronous waiting.
                else
                {
                    // If the count > 0 we are good to move on.
                    // If not, then wait if we were given allowed some wait duration

                    OperationCanceledException oce = null;

                    if (m_currentCount == 0)
                    {
                        if (millisecondsTimeout == 0)
                        {
                            return(false);
                        }

                        // Prepare for the main wait...
                        // wait until the count become greater than zero or the timeout is expired
                        try
                        {
                            waitSuccessful = WaitUntilCountOrTimeout(millisecondsTimeout, startTime, cancellationToken);
                        }
                        catch (OperationCanceledException e) { oce = e; }
                    }

                    // Now try to acquire.  We prioritize acquisition over cancellation/timeout so that we don't
                    // lose any counts when there are asynchronous waiters in the mix.  Asynchronous waiters
                    // defer to synchronous waiters in priority, which means that if it's possible an asynchronous
                    // waiter didn't get released because a synchronous waiter was present, we need to ensure
                    // that synchronous waiter succeeds so that they have a chance to release.
                    Contract.Assert(!waitSuccessful || m_currentCount > 0,
                                    "If the wait was successful, there should be count available.");
                    if (m_currentCount > 0)
                    {
                        waitSuccessful = true;
                        m_currentCount--;
                    }
                    else if (oce != null)
                    {
                        throw oce;
                    }

                    // Exposing wait handle which is lazily initialized if needed
                    if (m_waitHandle != null && m_currentCount == 0)
                    {
                        m_waitHandle.Reset();
                    }
                }
            }
            finally
            {
                // Release the lock
                if (lockTaken)
                {
                    m_waitCount--;
                    Monitor.Exit(m_lock);
                }

                // Unregister the cancellation callback.
                cancellationTokenRegistration.Dispose();
            }

            // If we had to fall back to asynchronous waiting, block on it
            // here now that we've released the lock, and return its
            // result when available.  Otherwise, this was a synchronous
            // wait, and whether we successfully acquired the semaphore is
            // stored in waitSuccessful.

            return((asyncWaitTask != null) ? asyncWaitTask.GetAwaiter().GetResult() : waitSuccessful);
        }
        public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken)
        {
            this.CheckDispose();
            if (millisecondsTimeout < -1)
            {
                throw new ArgumentOutOfRangeException("totalMilliSeconds", millisecondsTimeout, GetResourceString("SemaphoreSlim_Wait_TimeoutWrong"));
            }
            cancellationToken.ThrowIfCancellationRequested();
            long startTimeTicks = 0L;

            if ((millisecondsTimeout != -1) && (millisecondsTimeout > 0))
            {
                startTimeTicks = DateTime.UtcNow.Ticks;
            }
            bool lockTaken = false;
            CancellationTokenRegistration registration = cancellationToken.Register(s_cancellationTokenCanceledEventHandler, this);

            try
            {
                SpinWait wait = new SpinWait();
                while ((this.m_currentCount == 0) && !wait.NextSpinWillYield)
                {
                    wait.SpinOnce();
                }
                try
                {
                }
                finally
                {
                    Monitor.Enter(this.m_lockObj, ref lockTaken);
                    if (lockTaken)
                    {
                        this.m_waitCount++;
                    }
                }
                if (this.m_currentCount == 0)
                {
                    if (millisecondsTimeout == 0)
                    {
                        return(false);
                    }
                    if (!this.WaitUntilCountOrTimeout(millisecondsTimeout, startTimeTicks, cancellationToken))
                    {
                        return(false);
                    }
                }
                this.m_currentCount--;
                if ((this.m_waitHandle != null) && (this.m_currentCount == 0))
                {
                    this.m_waitHandle.Reset();
                }
            }
            finally
            {
                if (lockTaken)
                {
                    this.m_waitCount--;
                    Monitor.Exit(this.m_lockObj);
                }
                registration.Dispose();
            }
            return(true);
        }
Exemple #33
0
        public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken)
        {
            this.CheckDispose();
            if (millisecondsTimeout < -1)
            {
                throw new ArgumentOutOfRangeException("totalMilliSeconds", (object)millisecondsTimeout, SemaphoreSlim.GetResourceString("SemaphoreSlim_Wait_TimeoutWrong"));
            }
            cancellationToken.ThrowIfCancellationRequested();
            uint startTime = 0;

            if (millisecondsTimeout != -1 && millisecondsTimeout > 0)
            {
                startTime = TimeoutHelper.GetTime();
            }
            bool        flag      = false;
            Task <bool> task      = (Task <bool>)null;
            bool        lockTaken = false;
            CancellationTokenRegistration tokenRegistration = cancellationToken.InternalRegisterWithoutEC(SemaphoreSlim.s_cancellationTokenCanceledEventHandler, (object)this);

            try
            {
                SpinWait spinWait = new SpinWait();
                while (this.m_currentCount == 0 && !spinWait.NextSpinWillYield)
                {
                    spinWait.SpinOnce();
                }
                try
                {
                }
                finally
                {
                    Monitor.Enter(this.m_lockObj, ref lockTaken);
                    if (lockTaken)
                    {
                        this.m_waitCount = this.m_waitCount + 1;
                    }
                }
                if (this.m_asyncHead != null)
                {
                    task = this.WaitAsync(millisecondsTimeout, cancellationToken);
                }
                else
                {
                    OperationCanceledException canceledException = (OperationCanceledException)null;
                    if (this.m_currentCount == 0)
                    {
                        if (millisecondsTimeout == 0)
                        {
                            return(false);
                        }
                        try
                        {
                            flag = this.WaitUntilCountOrTimeout(millisecondsTimeout, startTime, cancellationToken);
                        }
                        catch (OperationCanceledException ex)
                        {
                            canceledException = ex;
                        }
                    }
                    if (this.m_currentCount > 0)
                    {
                        flag = true;
                        this.m_currentCount = this.m_currentCount - 1;
                    }
                    else if (canceledException != null)
                    {
                        throw canceledException;
                    }
                    if (this.m_waitHandle != null)
                    {
                        if (this.m_currentCount == 0)
                        {
                            this.m_waitHandle.Reset();
                        }
                    }
                }
            }
            finally
            {
                if (lockTaken)
                {
                    this.m_waitCount = this.m_waitCount - 1;
                    Monitor.Exit(this.m_lockObj);
                }
                tokenRegistration.Dispose();
            }
            if (task == null)
            {
                return(flag);
            }
            return(task.GetAwaiter().GetResult());
        }
        public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken)
        {
            CheckDispose();

            // Validate input
            if (millisecondsTimeout < -1)
            {
                throw new ArgumentOutOfRangeException(
                          nameof(millisecondsTimeout), millisecondsTimeout, SR.SemaphoreSlim_Wait_TimeoutWrong);
            }

            cancellationToken.ThrowIfCancellationRequested();

            // Perf: Check the stack timeout parameter before checking the volatile count
            if (millisecondsTimeout == 0 && m_currentCount == 0)
            {
                // Pessimistic fail fast, check volatile count outside lock (only when timeout is zero!)
                return(false);
            }

            uint startTime = 0;

            if (millisecondsTimeout != Timeout.Infinite && millisecondsTimeout > 0)
            {
                startTime = TimeoutHelper.GetTime();
            }

            bool        waitSuccessful = false;
            Task <bool>?asyncWaitTask  = null;
            bool        lockTaken      = false;

            // Register for cancellation outside of the main lock.
            // NOTE: Register/unregister inside the lock can deadlock as different lock acquisition orders could
            //      occur for (1)this.m_lockObjAndDisposed and (2)cts.internalLock
            CancellationTokenRegistration cancellationTokenRegistration = cancellationToken.UnsafeRegister(s_cancellationTokenCanceledEventHandler, this);

            try
            {
                // Perf: first spin wait for the count to be positive.
                // This additional amount of spinwaiting in addition
                // to Monitor.Enter()'s spinwaiting has shown measurable perf gains in test scenarios.
                if (m_currentCount == 0)
                {
                    // Monitor.Enter followed by Monitor.Wait is much more expensive than waiting on an event as it involves another
                    // spin, contention, etc. The usual number of spin iterations that would otherwise be used here is increased to
                    // lessen that extra expense of doing a proper wait.
                    int spinCount = SpinWait.SpinCountforSpinBeforeWait * 4;

                    SpinWait spinner = default;
                    while (spinner.Count < spinCount)
                    {
                        spinner.SpinOnce(sleep1Threshold: -1);

                        if (m_currentCount != 0)
                        {
                            break;
                        }
                    }
                }
                Monitor.Enter(m_lockObjAndDisposed, ref lockTaken);
                m_waitCount++;

                // If there are any async waiters, for fairness we'll get in line behind
                // then by translating our synchronous wait into an asynchronous one that we
                // then block on (once we've released the lock).
                if (m_asyncHead != null)
                {
                    Debug.Assert(m_asyncTail != null, "tail should not be null if head isn't");
                    asyncWaitTask = WaitAsync(millisecondsTimeout, cancellationToken);
                }
                // There are no async waiters, so we can proceed with normal synchronous waiting.
                else
                {
                    // If the count > 0 we are good to move on.
                    // If not, then wait if we were given allowed some wait duration

                    OperationCanceledException?oce = null;

                    if (m_currentCount == 0)
                    {
                        if (millisecondsTimeout == 0)
                        {
                            return(false);
                        }

                        // Prepare for the main wait...
                        // wait until the count become greater than zero or the timeout is expired
                        try
                        {
                            waitSuccessful = WaitUntilCountOrTimeout(millisecondsTimeout, startTime, cancellationToken);
                        }
                        catch (OperationCanceledException e) { oce = e; }
                    }

                    // Now try to acquire.  We prioritize acquisition over cancellation/timeout so that we don't
                    // lose any counts when there are asynchronous waiters in the mix.  Asynchronous waiters
                    // defer to synchronous waiters in priority, which means that if it's possible an asynchronous
                    // waiter didn't get released because a synchronous waiter was present, we need to ensure
                    // that synchronous waiter succeeds so that they have a chance to release.
                    Debug.Assert(!waitSuccessful || m_currentCount > 0,
                                 "If the wait was successful, there should be count available.");
                    if (m_currentCount > 0)
                    {
                        waitSuccessful = true;
                        m_currentCount--;
                    }
                    else if (oce != null)
                    {
                        throw oce;
                    }

                    // Exposing wait handle which is lazily initialized if needed
                    if (m_waitHandle != null && m_currentCount == 0)
                    {
                        m_waitHandle.Reset();
                    }
                }
            }
            finally
            {
                // Release the lock
                if (lockTaken)
                {
                    m_waitCount--;
                    Monitor.Exit(m_lockObjAndDisposed);
                }

                // Unregister the cancellation callback.
                cancellationTokenRegistration.Dispose();
            }

            // If we had to fall back to asynchronous waiting, block on it
            // here now that we've released the lock, and return its
            // result when available.  Otherwise, this was a synchronous
            // wait, and whether we successfully acquired the semaphore is
            // stored in waitSuccessful.

            return((asyncWaitTask != null) ? asyncWaitTask.GetAwaiter().GetResult() : waitSuccessful);
        }