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
- recordstatescratchpad.cs
- GridView.cs
- FontDialog.cs
- SortQueryOperator.cs
- ConnectionStringsExpressionBuilder.cs
- EventLogPermissionAttribute.cs
- HMACRIPEMD160.cs
- GeometryModel3D.cs
- WebCategoryAttribute.cs
- WebPart.cs
- FixedSOMTextRun.cs
- SiteMapNodeCollection.cs
- EmissiveMaterial.cs
- FakeModelItemImpl.cs
- FigureParaClient.cs
- BaseCodePageEncoding.cs
- CursorInteropHelper.cs
- XmlDeclaration.cs
- XmlFormatWriterGenerator.cs
- OpCodes.cs
- HttpPostLocalhostServerProtocol.cs
- MeasureItemEvent.cs
- ParseNumbers.cs
- XmlCollation.cs
- WebPartConnectionsCloseVerb.cs
- DynamicDataExtensions.cs
- StrongTypingException.cs
- BooleanConverter.cs
- DBSqlParserTable.cs
- MD5.cs
- XhtmlBasicObjectListAdapter.cs
- XmlBinaryReader.cs
- HttpCookieCollection.cs
- Content.cs
- SystemColorTracker.cs
- RuntimeWrappedException.cs
- Thread.cs
- Parameter.cs
- CanonicalFontFamilyReference.cs
- PerformanceCounterPermission.cs
- Int64.cs
- DispatcherTimer.cs
- ToolStripContainerDesigner.cs
- DataControlCommands.cs
- ElementHost.cs
- Point3DCollection.cs
- ConfigurationValue.cs
- objectresult_tresulttype.cs
- ArrowControl.xaml.cs
- XmlDataImplementation.cs
- DataControlFieldsEditor.cs
- PropertySegmentSerializationProvider.cs
- Psha1DerivedKeyGenerator.cs
- ProfileGroupSettings.cs
- TextSelectionHelper.cs
- _BaseOverlappedAsyncResult.cs
- XPathNodeIterator.cs
- Assembly.cs
- FileUtil.cs
- TitleStyle.cs
- GlobalEventManager.cs
- HwndSourceParameters.cs
- ConfigurationValidatorBase.cs
- NCryptSafeHandles.cs
- MediaPlayer.cs
- AffineTransform3D.cs
- TabControlEvent.cs
- JulianCalendar.cs
- ISAPIApplicationHost.cs
- AttributeEmitter.cs
- DoubleLink.cs
- Transform.cs
- ListViewHitTestInfo.cs
- SizeChangedEventArgs.cs
- Matrix3DConverter.cs
- BindingNavigator.cs
- ErrorInfoXmlDocument.cs
- StringHandle.cs
- PathFigureCollectionConverter.cs
- ColumnBinding.cs
- PEFileEvidenceFactory.cs
- TextContainerChangedEventArgs.cs
- XmlEncoding.cs
- ListViewGroup.cs
- XsdBuilder.cs
- JapaneseCalendar.cs
- ThreadSafeList.cs
- OneOf.cs
- LinearGradientBrush.cs
- SqlRewriteScalarSubqueries.cs
- RtType.cs
- TreeBuilderBamlTranslator.cs
- GenericUriParser.cs
- SqlColumnizer.cs
- RegisteredDisposeScript.cs
- WindowsIdentity.cs
- ColorTranslator.cs
- AttachInfo.cs
- HttpGetClientProtocol.cs
- securitycriticaldataformultiplegetandset.cs