File: PinnedArraySegment.cs

package info (click to toggle)
mono 6.8.0.105%2Bdfsg-3.3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 1,284,512 kB
  • sloc: cs: 11,172,132; xml: 2,850,069; ansic: 671,653; cpp: 122,091; perl: 59,366; javascript: 30,841; asm: 22,168; makefile: 20,093; sh: 15,020; python: 4,827; pascal: 925; sql: 859; sed: 16; php: 1
file content (69 lines) | stat: -rw-r--r-- 2,889 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
//------------------------------------------------------------------------------
// <copyright file="PinnedArraySegment.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>                                                                
//------------------------------------------------------------------------------

namespace System.Web.Util {
    using System;
    using System.Diagnostics.CodeAnalysis;
    using System.Runtime.InteropServices;
    using System.Security.Permissions;

    // Utility class for pinning an ArraySegment<T> so that it can be passed to unmanaged code.
    //
    // This type is not thread safe.

    [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
    internal sealed class PinnedArraySegment<T> : IDisposable {

        private int _count;
        private GCHandle _gcHandle;

        [SuppressMessage("Microsoft.Reliability", "CA2006:UseSafeHandleToEncapsulateNativeResources", Justification = @"This is a memory pointer, not a handle. The handle is in the _gcHandle field, and its lifetime is controlled by the caller.")]
        private IntPtr _pointer;

        internal unsafe PinnedArraySegment(ArraySegment<T> segment) {
            // Structs - like ArraySegment<T> - can be "torn" by malicious users trying to take
            // advantage of race conditions that occur as a result of their copy-by-value semantics.
            // Since we'll pass the ArraySegment<T> to unmanaged code, we need to perform validation
            // to make sure that this hasn't happened. The ArraySegment<T> constructor can be used
            // to perform this validation. (MSRC 10170)
            segment = new ArraySegment<T>(segment.Array, segment.Offset, segment.Count);

            _gcHandle = GCHandle.Alloc(segment.Array, GCHandleType.Pinned); // pin the array so that unmanaged code can access it
            _pointer = Marshal.UnsafeAddrOfPinnedArrayElement(segment.Array, segment.Offset);
            _count = segment.Count;
        }

        public int Count {
            get {
                ThrowIfDisposed();
                return _count;
            }
        }

        public IntPtr Pointer {
            get {
                ThrowIfDisposed();
                return _pointer;
            }
        }

        [SuppressMessage("Microsoft.Usage", "CA2216:DisposableTypesShouldDeclareFinalizer", Justification = @"We don't own native resources.")]
        public void Dispose() {
            if (_pointer != IntPtr.Zero) {
                // only free the GCHandle once
                _pointer = IntPtr.Zero;
                _gcHandle.Free();
            }
        }

        private void ThrowIfDisposed() {
            if (_pointer == IntPtr.Zero) {
                throw new ObjectDisposedException(GetType().FullName);
            }
        }

    }
}