Merge pull request #439 from mono-soc-2012/garyb/iconfix
[mono.git] / mcs / class / System / System.Threading / Semaphore.cs
index e7cb8811a9f729e2b1adc1abec12cfa65e882492..1e197fca87f8748426320a7f95071e0776f486fb 100644 (file)
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-#if NET_2_0
-
 using System.Runtime.ConstrainedExecution;
 using System.Runtime.InteropServices;
 using System.Security.AccessControl;
+using System.Runtime.CompilerServices;
+using System.IO;
 
 namespace System.Threading {
 
        [ComVisible (false)]
-       [MonoTODO ("not supported by the runtime")]
        public sealed class Semaphore : WaitHandle {
 
-               [MonoTODO]
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               private static extern IntPtr CreateSemaphore_internal (
+                       int initialCount, int maximumCount, string name,
+                       out bool createdNew);
+
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               private static extern int ReleaseSemaphore_internal (
+                       IntPtr handle, int releaseCount, out bool fail);
+
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+               private static extern IntPtr OpenSemaphore_internal (string name, SemaphoreRights rights, out MonoIOError error);
+               
+               private Semaphore (IntPtr handle)
+               {
+                       Handle = handle;
+               }
+               
                public Semaphore (int initialCount, int maximumCount)
                        : this (initialCount, maximumCount, null)
                {
                }
 
-               [MonoTODO]
                public Semaphore (int initialCount, int maximumCount, string name)
                {
                        if (initialCount < 0)
@@ -54,16 +68,19 @@ namespace System.Threading {
                        if (initialCount > maximumCount)
                                throw new ArgumentException ("initialCount > maximumCount");
 
-                       throw new NotImplementedException ();
+                       bool created;
+                       
+                       Handle = CreateSemaphore_internal (initialCount,
+                                                          maximumCount, name,
+                                                          out created);
                }
 
-               [MonoTODO]
                public Semaphore (int initialCount, int maximumCount, string name, out bool createdNew)
                        : this (initialCount, maximumCount, name, out createdNew, null)
                {
                }
 
-               [MonoTODO]
+               [MonoTODO ("CreateSemaphore_internal does not support access control, semaphoreSecurity is ignored")]
                public Semaphore (int initialCount, int maximumCount, string name, out bool createdNew, 
                        SemaphoreSecurity semaphoreSecurity)
                {
@@ -74,41 +91,51 @@ namespace System.Threading {
                        if (initialCount > maximumCount)
                                throw new ArgumentException ("initialCount > maximumCount");
 
-                       createdNew = false;
-                       throw new NotImplementedException ();
+                       Handle = CreateSemaphore_internal (initialCount,
+                                                          maximumCount, name,
+                                                          out createdNew);
                }
 
-               [MonoTODO]
                public SemaphoreSecurity GetAccessControl ()
                {
-                       throw new NotImplementedException ();
+                       return new SemaphoreSecurity (SafeWaitHandle,
+                                                     AccessControlSections.Owner |
+                                                     AccessControlSections.Group |
+                                                     AccessControlSections.Access);
                }
 
-               [MonoTODO]
                [PrePrepareMethod]
                [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
                public int Release ()
                {
-                       throw new NotImplementedException ();
+                       return (Release (1));
                }
 
-               [MonoTODO]
                [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
                public int Release (int releaseCount)
                {
                        if (releaseCount < 1)
                                throw new ArgumentOutOfRangeException ("releaseCount");
 
-                       throw new NotImplementedException ();
+                       int ret;
+                       bool fail;
+                       
+                       ret = ReleaseSemaphore_internal (Handle, releaseCount,
+                                                        out fail);
+
+                       if (fail) {
+                               throw new SemaphoreFullException ();
+                       }
+
+                       return (ret);
                }
 
-               [MonoTODO]
                public void SetAccessControl (SemaphoreSecurity semaphoreSecurity)
                {
                        if (semaphoreSecurity == null)
                                throw new ArgumentNullException ("semaphoreSecurity");
-
-                       throw new NotImplementedException ();
+                               
+                       semaphoreSecurity.PersistModifications (SafeWaitHandle);
                }
 
                // static methods
@@ -118,7 +145,6 @@ namespace System.Threading {
                        return OpenExisting (name, SemaphoreRights.Synchronize | SemaphoreRights.Modify);
                }
 
-               [MonoTODO]
                public static Semaphore OpenExisting (string name, SemaphoreRights rights)
                {
                        if (name == null)
@@ -126,9 +152,21 @@ namespace System.Threading {
                        if ((name.Length ==0) || (name.Length > 260))
                                throw new ArgumentException ("name", Locale.GetText ("Invalid length [1-260]."));
 
-                       throw new NotImplementedException ();
+                       MonoIOError error;
+                       IntPtr handle = OpenSemaphore_internal (name, rights,
+                                                               out error);
+                       if (handle == (IntPtr)null) {
+                               if (error == MonoIOError.ERROR_FILE_NOT_FOUND) {
+                                       throw new WaitHandleCannotBeOpenedException (Locale.GetText ("Named Semaphore handle does not exist: ") + name);
+                               } else if (error == MonoIOError.ERROR_ACCESS_DENIED) {
+                                       throw new UnauthorizedAccessException ();
+                               } else {
+                                       throw new IOException (Locale.GetText ("Win32 IO error: ") + error.ToString ());
+                               }
+                       }
+                       
+                       return(new Semaphore (handle));
                }
        }
 }
 
-#endif