Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / clr / src / BCL / System / Threading / CountdownEvent.cs / 1305376 / CountdownEvent.cs
// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== // =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ // // CountdownEvent.cs // //[....] // // A simple coordination data structure that we use for fork/join style parallelism. // // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- using System; using System.Diagnostics; using System.Security.Permissions; using System.Runtime.InteropServices; using System.Threading; using System.Diagnostics.Contracts; namespace System.Threading { ////// Represents a synchronization primitive that is signaled when its count reaches zero. /// ////// All public and protected members of [ComVisible(false)] [DebuggerDisplay("Initial Count={InitialCount}, Current Count={CurrentCount}")] [HostProtection(SecurityAction.LinkDemand, Synchronization = true, ExternalThreading = true)] public class CountdownEvent : IDisposable { // CountdownEvent is a simple synchronization primitive used for fork/join parallelism. We create a // latch with a count of N; threads then signal the latch, which decrements N by 1; other threads can // wait on the latch at any point; when the latch count reaches 0, all threads are woken and // subsequent waiters return without waiting. The implementation internally lazily creates a true // Win32 event as needed. We also use some amount of spinning on MP machines before falling back to a // wait. private int m_initialCount; // The original # of signals the latch was instantiated with. private volatile int m_currentCount; // The # of outstanding signals before the latch transitions to a signaled state. private ManualResetEventSlim m_event; // An event used to manage blocking and signaling. private volatile bool m_disposed; // Whether the latch has been disposed. ///are thread-safe and may be used /// concurrently from multiple threads, with the exception of Dispose, which /// must only be used when all other operations on the have /// completed, and Reset, which should only be used when no other threads are /// accessing the event. /// /// Initializes a new instance of /// The number of signals required to set theclass with the /// specified count. /// . /// public CountdownEvent(int initialCount) { if (initialCount < 0) { throw new ArgumentOutOfRangeException("initialCount"); } m_initialCount = initialCount; m_currentCount = initialCount; // Allocate a thin event, which internally defers creation of an actual Win32 event. m_event = new ManualResetEventSlim(); // If the latch was created with a count of 0, then it's already in the signaled state. if (initialCount == 0) { m_event.Set(); } } /// is less /// than 0. /// Gets the number of remaining signals required to set the event. /// ////// The number of remaining signals required to set the event. /// public int CurrentCount { get { return m_currentCount; } } ////// Gets the numbers of signals initially required to set the event. /// ////// The number of signals initially required to set the event. /// public int InitialCount { get { return m_initialCount; } } ////// Determines whether the event is set. /// ///true if the event is set; otherwise, false. public bool IsSet { get { // The latch is "completed" if its current count has reached 0. Note that this is NOT // the same thing is checking the event's IsCompleted property. There is a tiny window // of time, after the final decrement of the current count to 0 and before setting the // event, where the two values are out of [....]. return (m_currentCount == 0); } } ////// Gets a ///that is used to wait for the event to be set. /// A ///that is used to wait for the event to be set. The current instance has already been disposed. ////// public WaitHandle WaitHandle { get { ThrowIfDisposed(); return m_event.WaitHandle; } } ///should only be used if it's needed for integration with code bases /// that rely on having a WaitHandle. If all that's needed is to wait for the /// to be set, the method should be preferred. /// /// Releases all resources used by the current instance of ///. /// /// Unlike most of the members of public void Dispose() { // Gets rid of this latch's associated resources. This can consist of a Win32 event // which is (lazily) allocated by the underlying thin event. This method is not safe to // call concurrently -- i.e. a caller must coordinate to ensure only one thread is using // the latch at the time of the call to Dispose. Dispose(true); GC.SuppressFinalize(this); } ///, is not /// thread-safe and may not be used concurrently with other members of this instance. /// /// When overridden in a derived class, releases the unmanaged resources used by the /// /// true to release both managed and unmanaged resources; false to release /// only unmanaged resources. ///, and optionally releases the managed resources. /// /// Unlike most of the members of protected virtual void Dispose(bool disposing) { if (disposing) { m_event.Dispose(); m_disposed = true; } } ///, is not /// thread-safe and may not be used concurrently with other members of this instance. /// /// Registers a signal with the ///, decrementing its /// count. /// true if the signal caused the count to reach zero and the event was set; otherwise, /// false. ///The current instance is already set. /// ///The current instance has already been /// disposed. public bool Signal() { return Signal(1); } ////// Registers multiple signals with the /// The number of signals to register. ///, /// decrementing its count by the specified amount. /// true if the signals caused the count to reach zero and the event was set; otherwise, /// false. ////// The current instance is already set. -or- Or ///is greater than . /// /// is less /// than 1. The current instance has already been /// disposed. public bool Signal(int signalCount) { if (signalCount <= 0) { throw new ArgumentOutOfRangeException("signalCount"); } ThrowIfDisposed(); Contract.Assert(m_event != null); int observedCount; SpinWait spin = new SpinWait(); while (true) { observedCount = m_currentCount; // If the latch is already signaled, we will fail. if (observedCount < signalCount) { throw new InvalidOperationException(Environment.GetResourceString("CountdownEvent_Decrement_BelowZero")); } // This disables the "CS0420: a reference to a volatile field will not be treated as volatile" warning // for this statement. This warning is clearly senseless for Interlocked operations. #pragma warning disable 0420 if (Interlocked.CompareExchange(ref m_currentCount, observedCount - signalCount, observedCount) == observedCount) #pragma warning restore 0420 { break; } // The CAS failed. Spin briefly and try again. spin.SpinOnce(); } // If we were the last to signal, set the event. if (observedCount == signalCount) { m_event.Set(); return true; } Contract.Assert(m_currentCount >= 0, "latch was decremented below zero"); return false; } ////// Increments the ///'s current count by one. /// The current instance is already /// set. ////// is equal to . /// The current instance has already been disposed. /// public void AddCount() { AddCount(1); } ////// Attempts to increment the ///'s current count by one. /// true if the increment succeeded; otherwise, false. If ///is /// already at zero. this will return false. /// is equal to . The current instance has already been /// disposed. public bool TryAddCount() { return TryAddCount(1); } ////// Increments the /// The value by which to increase's current count by a specified /// value. /// . /// /// is less than /// 0. The current instance is already /// set. ////// is equal to . The current instance has already been /// disposed. public void AddCount(int signalCount) { if (!TryAddCount(signalCount)) { throw new InvalidOperationException(Environment.GetResourceString("CountdownEvent_Increment_AlreadyZero")); } } ////// Attempts to increment the /// The value by which to increase's current count by a /// specified value. /// . /// true if the increment succeeded; otherwise, false. If ///is /// already at zero this will return false. /// is less /// than 0. The current instance is already /// set. ////// is equal to . The current instance has already been /// disposed. public bool TryAddCount(int signalCount) { if (signalCount <= 0) { throw new ArgumentOutOfRangeException("signalCount"); } ThrowIfDisposed(); // Loop around until we successfully increment the count. int observedCount; SpinWait spin = new SpinWait(); while (true) { observedCount = m_currentCount; if (observedCount == 0) { return false; } else if (observedCount > (Int32.MaxValue - signalCount)) { throw new InvalidOperationException(Environment.GetResourceString("CountdownEvent_Increment_AlreadyMax")); } // This disables the "CS0420: a reference to a volatile field will not be treated as volatile" warning // for this statement. This warning is clearly senseless for Interlocked operations. #pragma warning disable 0420 if (Interlocked.CompareExchange(ref m_currentCount, observedCount + signalCount, observedCount) == observedCount) #pragma warning restore 0420 { break; } // The CAS failed. Spin briefly and try again. spin.SpinOnce(); } return true; } ////// Resets the ///to the value of . /// /// Unlike most of the members of ///, Reset is not /// thread-safe and may not be used concurrently with other members of this instance. /// The current instance has already been /// disposed.. public void Reset() { Reset(m_initialCount); } ////// Resets the /// The number of signals required to set theto a specified value. /// . /// /// Unlike most of the members of ///, Reset is not /// thread-safe and may not be used concurrently with other members of this instance. /// /// is /// less than 0. The current instance has alread been disposed. public void Reset(int count) { ThrowIfDisposed(); if (count < 0) { throw new ArgumentOutOfRangeException("count"); } m_currentCount = count; m_initialCount = count; if (count == 0) { m_event.Set(); } else { m_event.Reset(); } } ////// Blocks the current thread until the ///is set. /// /// The caller of this method blocks indefinitely until the current instance is set. The caller will /// return immediately if the event is currently in a set state. /// ///The current instance has already been /// disposed. public void Wait() { Wait(Timeout.Infinite, new CancellationToken()); } ////// Blocks the current thread until the /// Theis set, while /// observing a . /// to /// observe. /// /// The caller of this method blocks indefinitely until the current instance is set. The caller will /// return immediately if the event is currently in a set state. If the /// ///CancellationToken being observed /// is canceled during the wait operation, an/// will be thrown. /// /// has been /// canceled. The current instance has already been /// disposed. public void Wait(CancellationToken cancellationToken) { Wait(Timeout.Infinite, cancellationToken); } ////// Blocks the current thread until the /// Ais set, using a /// to measure the time interval. /// that represents the number of /// milliseconds to wait, or a that represents -1 milliseconds to /// wait indefinitely. /// true if the ///was set; otherwise, /// false. /// is a negative /// number other than -1 milliseconds, which represents an infinite time-out -or- timeout is greater /// than . The current instance has already been /// disposed. public bool Wait(TimeSpan timeout) { long totalMilliseconds = (long)timeout.TotalMilliseconds; if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue) { throw new ArgumentOutOfRangeException("timeout"); } return Wait((int)totalMilliseconds, new CancellationToken()); } ////// Blocks the current thread until the /// Ais set, using /// a to measure the time interval, while observing a /// . /// that represents the number of /// milliseconds to wait, or a that represents -1 milliseconds to /// wait indefinitely. /// The to /// observe. /// true if the ///was set; otherwise, /// false. /// is a negative /// number other than -1 milliseconds, which represents an infinite time-out -or- timeout is greater /// than . The current instance has already been /// disposed. ///public bool Wait(TimeSpan timeout, CancellationToken cancellationToken) { long totalMilliseconds = (long)timeout.TotalMilliseconds; if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue) { throw new ArgumentOutOfRangeException("timeout"); } return Wait((int)totalMilliseconds, cancellationToken); } /// has /// been canceled. /// Blocks the current thread until the /// The number of milliseconds to wait, oris set, using a /// 32-bit signed integer to measure the time interval. /// (-1) to wait indefinitely. /// true if the ///was set; otherwise, /// false. /// is a /// negative number other than -1, which represents an infinite time-out. The current instance has already been /// disposed. public bool Wait(int millisecondsTimeout) { return Wait(millisecondsTimeout, new CancellationToken()); } ////// Blocks the current thread until the /// The number of milliseconds to wait, oris set, using a /// 32-bit signed integer to measure the time interval, while observing a /// . /// (-1) to wait indefinitely. /// The to /// observe. /// true if the ///was set; otherwise, /// false. /// is a /// negative number other than -1, which represents an infinite time-out. The current instance has already been /// disposed. ///public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken) { if (millisecondsTimeout < -1) { throw new ArgumentOutOfRangeException("millisecondsTimeout"); } ThrowIfDisposed(); cancellationToken.ThrowIfCancellationRequested(); bool returnValue = IsSet; // If not completed yet, wait on the event. if (!returnValue) { // ** the actual wait returnValue = m_event.Wait(millisecondsTimeout, cancellationToken); //the Wait will throw OCE itself if the token is canceled. } return returnValue; } // -------------------------------------- // Private methods /// has /// been canceled. /// Throws an exception if the latch has been disposed. /// private void ThrowIfDisposed() { if (m_disposed) { throw new ObjectDisposedException("CountdownEvent"); } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ImportException.cs
- Expressions.cs
- NullEntityWrapper.cs
- EntityDataSourceQueryBuilder.cs
- InternalRelationshipCollection.cs
- CancellableEnumerable.cs
- XmlNodeReader.cs
- TaskCanceledException.cs
- WebPermission.cs
- XmlCharCheckingWriter.cs
- XmlIlGenerator.cs
- ThreadStartException.cs
- ModifierKeysConverter.cs
- IdentityElement.cs
- TextPatternIdentifiers.cs
- TableLayoutCellPaintEventArgs.cs
- NavigateEvent.cs
- LineBreak.cs
- XmlCharacterData.cs
- PenContexts.cs
- RequestTimeoutManager.cs
- NavigationWindowAutomationPeer.cs
- SqlNodeTypeOperators.cs
- ToolTip.cs
- ListViewVirtualItemsSelectionRangeChangedEvent.cs
- XPathScanner.cs
- DocumentCollection.cs
- NumericUpDown.cs
- RequestNavigateEventArgs.cs
- XmlSchemaGroupRef.cs
- XmlSchemaResource.cs
- SchemaInfo.cs
- diagnosticsswitches.cs
- HtmlTableRow.cs
- NetDataContractSerializer.cs
- SqlAliaser.cs
- StylusPointPropertyInfoDefaults.cs
- PerformanceCounterPermission.cs
- Calendar.cs
- BuildResultCache.cs
- ConditionalWeakTable.cs
- ExternalException.cs
- TransformerInfoCollection.cs
- BitmapPalette.cs
- TypeSemantics.cs
- UriParserTemplates.cs
- FieldBuilder.cs
- ToolStripSettings.cs
- MergeFailedEvent.cs
- sqlstateclientmanager.cs
- BasicExpandProvider.cs
- KeyTime.cs
- COM2PictureConverter.cs
- WebPartTransformerCollection.cs
- DemultiplexingClientMessageFormatter.cs
- InputBinder.cs
- HttpVersion.cs
- BindingMAnagerBase.cs
- ConfigurationValidatorAttribute.cs
- TextFormatter.cs
- TextTreeExtractElementUndoUnit.cs
- Documentation.cs
- NumberAction.cs
- HtmlControl.cs
- TimeSpanMinutesConverter.cs
- ScrollProperties.cs
- SapiRecoContext.cs
- RangeContentEnumerator.cs
- _DigestClient.cs
- NextPreviousPagerField.cs
- SemanticAnalyzer.cs
- TakeQueryOptionExpression.cs
- TreeNodeClickEventArgs.cs
- MultipleViewPattern.cs
- DataGridViewImageColumn.cs
- shaperfactoryquerycacheentry.cs
- PointLight.cs
- VerticalAlignConverter.cs
- RoutingExtensionElement.cs
- SpellerHighlightLayer.cs
- PolicyDesigner.cs
- HandlerBase.cs
- ComPlusContractBehavior.cs
- Command.cs
- listitem.cs
- BufferedWebEventProvider.cs
- ContextQuery.cs
- ViewStateException.cs
- ControlCollection.cs
- OracleConnectionFactory.cs
- Pkcs9Attribute.cs
- ExpressionVisitor.cs
- DeleteHelper.cs
- Visual.cs
- ShapingEngine.cs
- HuffmanTree.cs
- RuleSettingsCollection.cs
- EditingMode.cs
- assemblycache.cs
- ComboBox.cs