The Labs \ Source Viewer \ SSCLI \ System.IO \ PinnedBufferMemoryStream

  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. /*============================================================
  16. **
  17. ** Class:  PinnedBufferMemoryStream
  18. **
  19. **
  20. ** Purpose: Pins a byte[], exposing it as an unmanaged memory
  21. **          stream.  Used in ResourceReader for corner cases.
  22. **
  23. **
  24. ===========================================================*/
  25. using System;
  26. using System.Runtime.InteropServices;
  27. namespace System.IO
  28. {
  29.     unsafe internal sealed class PinnedBufferMemoryStream : UnmanagedMemoryStream
  30.     {
  31.         private byte[] _array;
  32.         private GCHandle _pinningHandle;
  33.        
  34.         internal PinnedBufferMemoryStream(byte[] array)
  35.         {
  36.             BCLDebug.Assert(array != null, "Array can't be null");
  37.            
  38.             int len = array.Length;
  39.             // Handle 0 length byte arrays specially.
  40.             if (len == 0) {
  41.                 array = new byte[1];
  42.                 len = 0;
  43.             }
  44.            
  45.             _array = array;
  46.             _pinningHandle = new GCHandle(array, GCHandleType.Pinned);
  47.             // Now the byte[] is pinned for the lifetime of this instance.
  48.             // But I also need to get a pointer to that block of memory...
  49.             fixed (byte* ptr = _array)
  50.                 Initialize(ptr, len, len, FileAccess.Read, true);
  51.         }
  52.        
  53.         ~PinnedBufferMemoryStream()
  54.         {
  55.             Dispose(false);
  56.         }
  57.        
  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. }

Developer Fusion