diff --git a/src/absil/bytes.fs b/src/absil/bytes.fs index 56f3a3c1aca2b1f4a9c01523b5bb41b84005904e..bc7ceb96b4617814b018e5de25e2aeab24908554 100644 --- a/src/absil/bytes.fs +++ b/src/absil/bytes.fs @@ -116,6 +116,36 @@ type ByteArrayMemory(bytes: byte[], offset, length) = override _.AsReadOnlyStream() = new MemoryStream(bytes, offset, length, false) :> Stream +[] +type SafeUnmanagedMemoryStream = + inherit UnmanagedMemoryStream + + val mutable private hold: obj + val mutable private isDisposed: bool + + new (addr, length, hold) = + { + inherit UnmanagedMemoryStream(addr, length) + hold = hold + isDisposed = false + } + + new (addr: nativeptr, length: int64, capacity: int64, access: FileAccess, hold) = + { + inherit UnmanagedMemoryStream(addr, length, capacity, access) + hold = hold + isDisposed = false + } + + override x.Finalize() = + x.Dispose false + + override x.Dispose disposing = + base.Dispose disposing + if not x.isDisposed then + x.hold <- null // Null out so it can be collected. + x.isDisposed <- true + [] type RawByteMemory(addr: nativeptr, length: int, hold: obj) = inherit ByteMemory () @@ -170,7 +200,7 @@ type RawByteMemory(addr: nativeptr, length: int, hold: obj) = use stream2 = x.AsStream() stream2.CopyTo stream - override x.Copy(srcOffset, dest, destOffset, count) = + override _.Copy(srcOffset, dest, destOffset, count) = check srcOffset Marshal.Copy(NativePtr.toNativeInt addr + nativeint srcOffset, dest, destOffset, count) @@ -180,10 +210,10 @@ type RawByteMemory(addr: nativeptr, length: int, hold: obj) = res override _.AsStream() = - new UnmanagedMemoryStream(addr, int64 length) :> Stream + new SafeUnmanagedMemoryStream(addr, int64 length, hold) :> Stream override _.AsReadOnlyStream() = - new UnmanagedMemoryStream(addr, int64 length, int64 length, FileAccess.Read) :> Stream + new SafeUnmanagedMemoryStream(addr, int64 length, int64 length, FileAccess.Read, hold) :> Stream [] type ReadOnlyByteMemory(bytes: ByteMemory) =