ProteoWizard
pinned_gcroot.h
Go to the documentation of this file.
1 //
2 // $Id$
3 //
4 //
5 // Original author: Matt Chambers <matt.chambers .@. vanderbilt.edu>
6 //
7 // Copyright (c) Microsoft Corporation. All rights reserved.
8 //
9 // Slightly modified version of gcroot.h that pins the GCHandle and allows access to the handle.
10 //
11 
12 #pragma once
13 #include <gcroot.h>
14 
15 #ifdef __cplusplus_cli
16 #define __GCHANDLE_TO_VOIDPTR(x) ((GCHandle::operator System::IntPtr(x)).ToPointer())
17 #define __VOIDPTR_TO_GCHANDLE(x) (GCHandle::operator GCHandle(System::IntPtr(x)))
18 #define __NULLPTR nullptr
19 #else /* __cplusplus_cli */
20 #define __GCHANDLE_TO_VOIDPTR(x) ((GCHandle::op_Explicit(x)).ToPointer())
21 #define __VOIDPTR_TO_GCHANDLE(x) (GCHandle::op_Explicit(x))
22 #define __NULLPTR 0
23 #endif /* __cplusplus_cli */
24 
25 #ifndef __DEFINE_GCROOT_IN_GLOBAL_NAMESPACE
26 namespace msclr
27 {
28 #endif /* __DEFINE_GCROOT_IN_GLOBAL_NAMESPACE */
29 
30  /// pinned_gcroot: a slightly modified gcroot that pins its GCHandle
31  template <class T> struct pinned_gcroot {
32 
33  typedef System::Runtime::InteropServices::GCHandle GCHandle;
34  typedef System::Runtime::InteropServices::GCHandleType GCHandleType;
35 
36  // always allocate a new handle during construction (see above)
37  //
38  // Initializes to a NULL handle, which is always safe
39  [System::Diagnostics::DebuggerStepThroughAttribute]
40  [System::Security::SecuritySafeCritical]
42  _handle = __GCHANDLE_TO_VOIDPTR(GCHandle::Alloc(__NULLPTR, GCHandleType::Pinned));
43  }
44 
45  // this can't be T& here because & does not yet work on managed types
46  // (T should be a pointer anyway).
47  //
49  _handle = __GCHANDLE_TO_VOIDPTR(GCHandle::Alloc(t, GCHandleType::Pinned));
50  }
51 
53  // don't copy a handle, copy what it points to (see above)
55  GCHandle::Alloc(
56  __VOIDPTR_TO_GCHANDLE(r._handle).Target, GCHandleType::Pinned));
57  }
58 
59  // Since C++ objects and handles are allocated 1-to-1, we can
60  // free the handle when the object is destroyed
61  //
62  [System::Diagnostics::DebuggerStepThroughAttribute]
63  [System::Security::SecurityCritical]
66  g.Free();
67  _handle = 0; // should fail if reconstituted
68  }
69 
70  [System::Diagnostics::DebuggerStepThroughAttribute]
71  [System::Security::SecurityCritical]
73  // no need to check for valid handle; was allocated in ctor
74  __VOIDPTR_TO_GCHANDLE(_handle).Target = t;
75  return *this;
76  }
77 
79  // no need to check for valid handle; was allocated in ctor
80  T t = (T)r;
81  __VOIDPTR_TO_GCHANDLE(_handle).Target = t;
82  return *this;
83  }
84 
85  void swap(pinned_gcroot<T> & _right)
86  {
87  using std::swap;
88  swap(_handle, _right._handle);
89  }
90 
91  // The managed object is not a secret or protected resource, so it's okay to expose to anyone who has access to the gcroot object
92  [System::Security::SecuritySafeCritical]
93  operator T () const {
94  // gcroot is typesafe, so use static_cast
95  return static_cast<T>(__VOIDPTR_TO_GCHANDLE(_handle).Target);
96  }
97 
98  // don't return T& here because & to gc pointer not yet implemented
99  // (T should be a pointer anyway).
100  [System::Security::SecuritySafeCritical]
101  T operator->() const {
102  // gcroot is typesafe, so use static_cast
103  return static_cast<T>(__VOIDPTR_TO_GCHANDLE(_handle).Target);
104  }
105 
106  System::IntPtr operator& () const {
107  return __VOIDPTR_TO_GCHANDLE(_handle).AddrOfPinnedObject();
108  }
109 
110  void* handle() const {
111  return _handle;
112  }
113 
114  private:
115  // Don't let anyone copy the handle value directly, or make a copy
116  // by taking the address of this object and pointing to it from
117  // somewhere else. The root will be freed when the dtor of this
118  // object gets called, and anyone pointing to it still will
119  // cause serious harm to the Garbage Collector.
120  //
121  void* _handle;
122  };
123 
124  template<typename T>
125  void swap(pinned_gcroot<T> & _left,
126  pinned_gcroot<T> & _right)
127  {
128  _left.swap(_right);
129  }
130 
131 #ifndef __DEFINE_GCROOT_IN_GLOBAL_NAMESPACE
132 } // namespace msclr
133 #endif /* __DEFINE_GCROOT_IN_GLOBAL_NAMESPACE */
134 
135 #undef __GCHANDLE_TO_VOIDPTR
136 #undef __VOIDPTR_TO_GCHANDLE
137 #undef __NULLPTR
138 
139 
msclr::pinned_gcroot::GCHandle
System::Runtime::InteropServices::GCHandle GCHandle
Definition: pinned_gcroot.h:33
msclr::pinned_gcroot::pinned_gcroot
pinned_gcroot(T t)
Definition: pinned_gcroot.h:48
msclr::pinned_gcroot::_handle
void * _handle
Definition: pinned_gcroot.h:121
msclr::pinned_gcroot::operator&
System::IntPtr operator&() const
Definition: pinned_gcroot.h:106
__VOIDPTR_TO_GCHANDLE
#define __VOIDPTR_TO_GCHANDLE(x)
Definition: pinned_gcroot.h:21
__GCHANDLE_TO_VOIDPTR
#define __GCHANDLE_TO_VOIDPTR(x)
Definition: pinned_gcroot.h:20
msclr::pinned_gcroot::operator=
pinned_gcroot & operator=(T t)
Definition: pinned_gcroot.h:72
msclr
Definition: pinned_gcroot.h:27
msclr::pinned_gcroot::pinned_gcroot
pinned_gcroot(const pinned_gcroot &r)
Definition: pinned_gcroot.h:52
__NULLPTR
#define __NULLPTR
Definition: pinned_gcroot.h:22
msclr::pinned_gcroot
pinned_gcroot: a slightly modified gcroot that pins its GCHandle
Definition: pinned_gcroot.h:31
msclr::pinned_gcroot::~pinned_gcroot
~pinned_gcroot()
Definition: pinned_gcroot.h:64
msclr::pinned_gcroot::swap
void swap(pinned_gcroot< T > &_right)
Definition: pinned_gcroot.h:85
msclr::pinned_gcroot::operator->
T operator->() const
Definition: pinned_gcroot.h:101
msclr::pinned_gcroot::pinned_gcroot
pinned_gcroot()
Definition: pinned_gcroot.h:41
msclr::pinned_gcroot::operator=
pinned_gcroot & operator=(const pinned_gcroot &r)
Definition: pinned_gcroot.h:78
msclr::pinned_gcroot::handle
void * handle() const
Definition: pinned_gcroot.h:110
msclr::pinned_gcroot::GCHandleType
System::Runtime::InteropServices::GCHandleType GCHandleType
Definition: pinned_gcroot.h:34
msclr::swap
void swap(pinned_gcroot< T > &_left, pinned_gcroot< T > &_right)
Definition: pinned_gcroot.h:125