The Labs \ Source Viewer \ SSCLI \ System.Threading \ Semaphore

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. namespace System.Threading
  16. {
  17.     using System.IO;
  18.     using System.IO.Ports;
  19.     using Microsoft.Win32;
  20.     using Microsoft.Win32.SafeHandles;
  21.     using System.Runtime.InteropServices;
  22.     using System.Threading;
  23.     using System.Security.Permissions;
  24.     using System.Runtime.Versioning;
  25.     using System.Runtime.ConstrainedExecution;
  26.    
  27.    
  28.     [HostProtection(Synchronization = true, ExternalThreading = true)]
  29.     [ComVisibleAttribute(false)]
  30.     public sealed class Semaphore : WaitHandle
  31.     {
  32.         private static int MAX_PATH = 260;
  33.         // creates a nameless semaphore object
  34.         // Win32 only takes maximum count of Int32.MaxValue
  35.         [ResourceExposure(ResourceScope.None)]
  36.         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
  37.         public Semaphore(int initialCount, int maximumCount) : this(initialCount, maximumCount, null)
  38.         {
  39.         }
  40.        
  41.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
  42.         [ResourceExposure(ResourceScope.Machine)]
  43.         [ResourceConsumption(ResourceScope.Machine)]
  44.         public Semaphore(int initialCount, int maximumCount, string name)
  45.         {
  46.             if (initialCount < 0) {
  47.                 throw new ArgumentOutOfRangeException("initialCount", SR.GetString(SR.ArgumentOutOfRange_NeedNonNegNumRequired));
  48.             }
  49.            
  50.             if (maximumCount < 1) {
  51.                 throw new ArgumentOutOfRangeException("maximumCount", SR.GetString(SR.ArgumentOutOfRange_NeedNonNegNumRequired));
  52.             }
  53.            
  54.             if (initialCount > maximumCount) {
  55.                 throw new ArgumentException(SR.GetString(SR.Argument_SemaphoreInitialMaximum));
  56.             }
  57.            
  58.             if (null != name && MAX_PATH < name.Length) {
  59.                 throw new ArgumentException(SR.GetString(SR.Argument_WaitHandleNameTooLong));
  60.             }
  61.             SafeWaitHandle myHandle = SafeNativeMethods.CreateSemaphore(null, initialCount, maximumCount, name);
  62.            
  63.             if (myHandle.IsInvalid) {
  64.                 int errorCode = Marshal.GetLastWin32Error();
  65.                
  66.                 if (null != name && 0 != name.Length && NativeMethods.ERROR_INVALID_HANDLE == errorCode)
  67.                     throw new WaitHandleCannotBeOpenedException(SR.GetString(SR.WaitHandleCannotBeOpenedException_InvalidHandle, name));
  68.                
  69.                 InternalResources.WinIOError();
  70.             }
  71.             this.SafeWaitHandle = myHandle;
  72.         }
  73.        
  74.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
  75.         [ResourceExposure(ResourceScope.Machine)]
  76.         [ResourceConsumption(ResourceScope.Machine)]
  77.         public Semaphore(int initialCount, int maximumCount, string name, out bool createdNew)
  78.         {
  79.             if (initialCount < 0) {
  80.                 throw new ArgumentOutOfRangeException("initialCount", SR.GetString(SR.ArgumentOutOfRange_NeedNonNegNumRequired));
  81.             }
  82.            
  83.             if (maximumCount < 1) {
  84.                 throw new ArgumentOutOfRangeException("maximumCount", SR.GetString(SR.ArgumentOutOfRange_NeedNonNegNumRequired));
  85.             }
  86.            
  87.             if (initialCount > maximumCount) {
  88.                 throw new ArgumentException(SR.GetString(SR.Argument_SemaphoreInitialMaximum));
  89.             }
  90.            
  91.             if (null != name && MAX_PATH < name.Length) {
  92.                 throw new ArgumentException(SR.GetString(SR.Argument_WaitHandleNameTooLong));
  93.             }
  94.             SafeWaitHandle myHandle;
  95.             myHandle = SafeNativeMethods.CreateSemaphore(null, initialCount, maximumCount, name);
  96.             int errorCode = Marshal.GetLastWin32Error();
  97.             if (myHandle.IsInvalid) {
  98.                 if (null != name && 0 != name.Length && NativeMethods.ERROR_INVALID_HANDLE == errorCode)
  99.                     throw new WaitHandleCannotBeOpenedException(SR.GetString(SR.WaitHandleCannotBeOpenedException_InvalidHandle, name));
  100.                 InternalResources.WinIOError();
  101.             }
  102.             createdNew = errorCode != NativeMethods.ERROR_ALREADY_EXISTS;
  103.             this.SafeWaitHandle = myHandle;
  104.         }
  105.        
  106.         private Semaphore(SafeWaitHandle handle)
  107.         {
  108.             this.SafeWaitHandle = handle;
  109.         }
  110.        
  111.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
  112.         [ResourceExposure(ResourceScope.Machine)]
  113.         [ResourceConsumption(ResourceScope.Machine)]
  114.         public static Semaphore OpenExisting(string name)
  115.         {
  116.             if (name == null) {
  117.                 throw new ArgumentNullException("name");
  118.             }
  119.             if (name.Length == 0) {
  120.                 throw new ArgumentException(SR.GetString(SR.InvalidNullEmptyArgument, "name"), "name");
  121.             }
  122.             if (null != name && MAX_PATH < name.Length) {
  123.                 throw new ArgumentException(SR.GetString(SR.Argument_WaitHandleNameTooLong));
  124.             }
  125.             //Pass false to OpenSemaphore to prevent inheritedHandles
  126.             SafeWaitHandle myHandle = SafeNativeMethods.OpenSemaphore(NativeMethods.SEMAPHORE_MODIFY_STATE | NativeMethods.SYNCHRONIZE, false, name);
  127.            
  128.             if (myHandle.IsInvalid) {
  129.                 int errorCode = Marshal.GetLastWin32Error();
  130.                
  131.                 if (NativeMethods.ERROR_FILE_NOT_FOUND == errorCode || NativeMethods.ERROR_INVALID_NAME == errorCode)
  132.                     throw new WaitHandleCannotBeOpenedException();
  133.                 if (null != name && 0 != name.Length && NativeMethods.ERROR_INVALID_HANDLE == errorCode)
  134.                     throw new WaitHandleCannotBeOpenedException(SR.GetString(SR.WaitHandleCannotBeOpenedException_InvalidHandle, name));
  135.                 //this is for passed through NativeMethods Errors
  136.                 InternalResources.WinIOError();
  137.             }
  138.             return new Semaphore(myHandle);
  139.         }
  140.        
  141.        
  142.         // increase the count on a semaphore, returns previous count
  143.         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  144.         [PrePrepareMethod()]
  145.         public int Release()
  146.         {
  147.             return Release(1);
  148.         }
  149.        
  150.         // increase the count on a semaphore, returns previous count
  151.         [ResourceExposure(ResourceScope.None)]
  152.         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
  153.         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  154.         public int Release(int releaseCount)
  155.         {
  156.             if (releaseCount < 1) {
  157.                 throw new ArgumentOutOfRangeException("releaseCount", SR.GetString(SR.ArgumentOutOfRange_NeedNonNegNumRequired));
  158.             }
  159.             int previousCount;
  160.            
  161.             //If ReleaseSempahore returns false when the specified value would cause
  162.             // the semaphore's count to exceed the maximum count set when Semaphore was created
  163.             //Non-Zero return
  164.            
  165.             if (!SafeNativeMethods.ReleaseSemaphore(SafeWaitHandle, releaseCount, out previousCount)) {
  166.                 throw new SemaphoreFullException();
  167.             }
  168.            
  169.             return previousCount;
  170.         }
  171.        
  172.     }
  173. }

Developer Fusion