Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / mscorlib / system / io / pinnedbuffermemorystream.cs
1 // ==++==
2 // 
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 // 
5 // ==--==
6 /*============================================================
7 **
8 ** Class:  PinnedBufferMemoryStream
9 ** 
10 ** <OWNER>Microsoft</OWNER>
11 **
12 **
13 ** Purpose: Pins a byte[], exposing it as an unmanaged memory 
14 **          stream.  Used in ResourceReader for corner cases.
15 **
16 **
17 ===========================================================*/
18 using System;
19 using System.Runtime.InteropServices;
20 using System.Diagnostics.Contracts;
21
22 namespace System.IO {
23     internal sealed unsafe class PinnedBufferMemoryStream : UnmanagedMemoryStream
24     {
25         private byte[] _array;
26         private GCHandle _pinningHandle;
27
28         // The new inheritance model requires a Critical default ctor since base (UnmanagedMemoryStream) has one
29         [System.Security.SecurityCritical]
30         private PinnedBufferMemoryStream():base(){}
31
32         [System.Security.SecurityCritical]  // auto-generated
33         internal PinnedBufferMemoryStream(byte[] array)
34         {
35             Contract.Assert(array != null, "Array can't be null");
36
37             int len = array.Length;
38             // Handle 0 length byte arrays specially.
39             if (len == 0) {
40                 array = new byte[1];
41                 len = 0;
42             }
43
44             _array = array;
45             _pinningHandle = new GCHandle(array, GCHandleType.Pinned);
46             // Now the byte[] is pinned for the lifetime of this instance.
47             // But I also need to get a pointer to that block of memory...
48             fixed(byte* ptr = _array)
49                 Initialize(ptr, len, len, FileAccess.Read, true);
50         }
51
52         ~PinnedBufferMemoryStream()
53         {
54             Dispose(false);
55         }
56
57         [System.Security.SecuritySafeCritical]  // auto-generated
58         protected override void Dispose(bool disposing)
59         {
60             if (_isOpen) {
61                 _pinningHandle.Free();
62                 _isOpen = false;
63             }
64 #if _DEBUG
65             // To help track down lifetime issues on checked builds, force 
66             //a full GC here.
67             if (disposing) {
68                 GC.Collect();
69                 GC.WaitForPendingFinalizers();
70             }
71 #endif
72             base.Dispose(disposing);
73         }
74     }
75 }