2006-12-02 Miguel de Icaza <miguel@novell.com>
authorMiguel de Icaza <miguel@gnome.org>
Sat, 2 Dec 2006 05:27:35 +0000 (05:27 -0000)
committerMiguel de Icaza <miguel@gnome.org>
Sat, 2 Dec 2006 05:27:35 +0000 (05:27 -0000)
* SafeHandle.cs: Implement this class.

2006-12-02  Miguel de Icaza  <miguel@novell.com>

* SafeFileHandle.cs: Remove the IsInvalid method, as that is
present in the base class.

svn path=/trunk/mcs/; revision=68875

mcs/class/corlib/Microsoft.Win32.SafeHandles/ChangeLog
mcs/class/corlib/Microsoft.Win32.SafeHandles/SafeFileHandle.cs
mcs/class/corlib/System.Runtime.InteropServices/ChangeLog
mcs/class/corlib/System.Runtime.InteropServices/SafeHandle.cs

index 1b5b481604f99ba537898d9ef0b768c9708c9108..f73cd7aaaac70ce843482dba0cecd5f282b05aa6 100644 (file)
@@ -1,3 +1,8 @@
+2006-12-02  Miguel de Icaza  <miguel@novell.com>
+
+       * SafeFileHandle.cs: Remove the IsInvalid method, as that is
+       present in the base class.
+
 2006-01-12  Ben Maurer  <bmaurer@andrew.cmu.edu>
 
        * SafeHandleZeroOrMinusOneIsInvalid.cs: Update to RTM api
index b98018a0516f6e8eac997bc53fb639778df49acf..7bd704097ebcdd8584a2307d5cbc86509d5bdb3e 100644 (file)
@@ -40,13 +40,6 @@ namespace Microsoft.Win32.SafeHandles {
                        SetHandle (preexistingHandle);
                }
 
-               [MonoTODO("Not implemented")]
-               public override bool IsInvalid {
-                       get {
-                               throw new NotImplementedException ();
-                       }
-               }
-
                [MonoTODO("Not implemented")]
                protected override bool ReleaseHandle ()
                {
index 3b4210b3e9465504f12595138ef14940c146b103..f8bce2c0781fef3ed3a5407d1ae470be9c14635a 100644 (file)
@@ -1,3 +1,7 @@
+2006-12-02  Miguel de Icaza  <miguel@novell.com>
+
+       * SafeHandle.cs: Implement this class.
+       
 2006-10-06  Jonathan Chambers  <joncham@gmail.com>
 
        * ExtensibleClassFactory.cs: Implement RegisterObjectCreationCallback.
index 3efec0fa14fd5a2b6da4dbf6f8246dc436015f1d..d7527d8c83d2b00d038b9b77a5dede82d60dd5f2 100644 (file)
 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
+// Notes:
+//     This code is only API complete, but it lacks the runtime support
+//     for CriticalFinalizerObject and any P/Invoke wrapping that might
+//     happen.
+//
+//     For details, see:
+//     http://blogs.msdn.com/cbrumme/archive/2004/02/20/77460.aspx
+//
 
 #if NET_2_0
 using System;
@@ -30,62 +38,101 @@ using System.Runtime.ConstrainedExecution;
 
 namespace System.Runtime.InteropServices
 {
-       [MonoTODO("Not implemented")]
        public abstract class SafeHandle : CriticalFinalizerObject, IDisposable {
+               object handle_lock = new object ();
                protected IntPtr handle;
-
-               [MonoTODO("Not implemented")]
+               IntPtr invalid_handle_value;
+               int refcount = 0;
+               bool owns_handle;
+               
                protected SafeHandle (IntPtr invalidHandleValue, bool ownsHandle)
                {
-                       throw new NotImplementedException ();
+                       invalid_handle_value = invalidHandleValue;
+                       owns_handle = ownsHandle;
+                       refcount = 1;
                }
 
-               [MonoTODO("Not implemented")]
-               public void Close () {
-                       throw new NotImplementedException ();
+               public void Close ()
+               {
+                       lock (handle_lock){
+                               refcount--;
+                               if (refcount == 0){
+                                       ReleaseHandle ();
+                                       handle = invalid_handle_value;
+                               }
+                       }
                }
 
-               [MonoTODO("Not implemented")]
-               public void DangerousAddRef (ref bool success) {
-                       throw new NotImplementedException ();
+               //
+               // I do not know when we could not be able to increment the
+               // reference count and set success to false.   It might just
+               // be a convention used for the following code pattern:
+               //
+               // bool release = false
+               // try { x.DangerousAddRef (ref release); ... }
+               // finally { if (release) x.DangerousRelease (); }
+               //
+               public void DangerousAddRef (ref bool success)
+               {
+                       lock (handle_lock){
+                               refcount++;
+                               success = true;
+                       }
                }
 
-               [MonoTODO("Not implemented")]
-               public IntPtr DangerousGetHandle () {
-                       throw new NotImplementedException ();
+               public IntPtr DangerousGetHandle ()
+               {
+                       return handle;
                }
 
-               [MonoTODO("Not implemented")]
-               public void DangerousRelease () {
-                       throw new NotImplementedException ();
+               public void DangerousRelease ()
+               {
+                       lock (handle_lock){
+                               refcount--;
+                               if (refcount == 0)
+                                       ReleaseHandle ();
+                       }
                }
 
-               [MonoTODO("Not implemented")]
-               public virtual void Dispose () {
-                       throw new NotImplementedException ();
+               public virtual void Dispose ()
+               {
+                       Dispose (true);
+                       GC.SuppressFinalize (this);
                }
 
-               [MonoTODO("Not implemented")]
-               public void SetHandleAsInvalid () {
-                       throw new NotImplementedException ();
+               //
+               // See documentation, this invalidates the handle without
+               // closing it.
+               //
+               public void SetHandleAsInvalid ()
+               {
+                       handle = invalid_handle_value;
                }
                
-               [MonoTODO("Not implemented")]
-               protected virtual void Dispose (bool disposing) {
-                       throw new NotImplementedException ();
+               protected virtual void Dispose (bool disposing)
+               {
+                       if (disposing)
+                               Close ();
+                       else {
+                               //
+                               // The docs say `never call this with disposing=false',
+                               // the question is whether:
+                               //   * The runtime will ever call Dipose(false) for SafeHandles (special runtime case)
+                               //   * Whether we should just call ReleaseHandle regardless?
+                               // 
+                       }
                }
 
                protected abstract bool ReleaseHandle ();
 
-               [MonoTODO("Not implemented")]
-               protected void SetHandle (IntPtr handle) {
-                       throw new NotImplementedException ();
+               protected void SetHandle (IntPtr handle)
+               {
+                       this.handle = handle;
                }
 
-               [MonoTODO("Not implemented")]
                public bool IsClosed {
                        get {
-                               throw new NotImplementedException ();
+                               return refcount == 0;
                        }
                }