STLdoc
STLdocumentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
gcroot.h
Go to the documentation of this file.
1 /***
2 *gcroot.h
3 *
4 * Copyright (c) Microsoft Corporation. All rights reserved.
5 *
6 *Purpose: Template class that wraps GCHandle from mscorlib.dll.
7 *
8 * Use this class to declare gc "pointers" that live in the C++ heap.
9 *
10 * Example:
11 * struct StringList {
12 * msclr::gcroot<String^> str;
13 * StringList *next;
14 * StringList(); // should have ctors and dtors
15 * ~StringList();
16 * };
17 *
18 * By convention, we maintain a 1-to-1 relationship between C++ objects
19 * and the handle slots they "point" to. Thus, two distinct C++ objects
20 * always refer to two distinct handles, even if they "point" to the same
21 * object. Therefore, when the C++ object is destroyed, its handle can
22 * be freed without error.
23 *
24 * Note that we cannot currently embed a GCHandle directly in an unmanaged C++
25 * class. We therefore store a void*, and use the conversion methods of
26 * GCHandle to reconstitute a GCHandle from the void* on demand.
27 *
28 * [Public]
29 *
30 ****/
31 
32 #pragma once
33 
34 #if !defined (_INC_MSCLR_GCROOT)
35 #define _INC_MSCLR_GCROOT
36 #ifndef RC_INVOKED
37 
38 #include <stddef.h>
39 
40 
41 #ifdef __cplusplus_cli
42  #define __GCHANDLE_TO_VOIDPTR(x) ((GCHandle::operator System::IntPtr(x)).ToPointer())
43  #define __VOIDPTR_TO_GCHANDLE(x) (GCHandle::operator GCHandle(System::IntPtr(x)))
44  #define __NULLPTR nullptr
45 #else /* __cplusplus_cli */
46  #define __GCHANDLE_TO_VOIDPTR(x) ((GCHandle::op_Explicit(x)).ToPointer())
47  #define __VOIDPTR_TO_GCHANDLE(x) (GCHandle::op_Explicit(x))
48  #define __NULLPTR 0
49 #endif /* __cplusplus_cli */
50 
51 #ifndef __DEFINE_GCROOT_IN_GLOBAL_NAMESPACE
52 namespace msclr
53 {
54 #endif /* __DEFINE_GCROOT_IN_GLOBAL_NAMESPACE */
55 
56 template <class T> struct gcroot {
57 
58  typedef System::Runtime::InteropServices::GCHandle GCHandle;
59 
60  // always allocate a new handle during construction (see above)
61  //
62  // Initializes to a NULL handle, which is always safe
63  [System::Diagnostics::DebuggerStepThroughAttribute]
64  [System::Security::SecuritySafeCritical]
65  gcroot() {
67  }
68 
69  // this can't be T& here because & does not yet work on managed types
70  // (T should be a pointer anyway).
71  //
72  gcroot(T t) {
74  }
75 
76  gcroot(const gcroot& r) {
77  // don't copy a handle, copy what it points to (see above)
80  __VOIDPTR_TO_GCHANDLE(r._handle).Target ));
81  }
82 
83  // Since C++ objects and handles are allocated 1-to-1, we can
84  // free the handle when the object is destroyed
85  //
86  [System::Diagnostics::DebuggerStepThroughAttribute]
87  [System::Security::SecurityCritical]
88  ~gcroot() {
89  GCHandle g = __VOIDPTR_TO_GCHANDLE(_handle);
90  g.Free();
91  _handle = 0; // should fail if reconstituted
92  }
93 
94  [System::Diagnostics::DebuggerStepThroughAttribute]
95  [System::Security::SecurityCritical]
96  gcroot& operator=(T t) {
97  // no need to check for valid handle; was allocated in ctor
98  __VOIDPTR_TO_GCHANDLE(_handle).Target = t;
99  return *this;
100  }
101 
102  gcroot& operator=(const gcroot &r) {
103  // no need to check for valid handle; was allocated in ctor
104  T t = (T)r;
105  __VOIDPTR_TO_GCHANDLE(_handle).Target = t;
106  return *this;
107  }
108 
109  void swap( gcroot<T> & _right )
110  {
111  using std::swap;
112  swap( _handle, _right._handle );
113  }
114 
115  // 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
116  [System::Security::SecuritySafeCritical]
117  operator T () const {
118  // gcroot is typesafe, so use static_cast
119  return static_cast<T>( __VOIDPTR_TO_GCHANDLE(_handle).Target );
120  }
121 
122  // don't return T& here because & to gc pointer not yet implemented
123  // (T should be a pointer anyway).
124  [System::Security::SecuritySafeCritical]
125  T operator->() const {
126  // gcroot is typesafe, so use static_cast
127  return static_cast<T>(__VOIDPTR_TO_GCHANDLE(_handle).Target);
128  }
129 
130 private:
131  // Don't let anyone copy the handle value directly, or make a copy
132  // by taking the address of this object and pointing to it from
133  // somewhere else. The root will be freed when the dtor of this
134  // object gets called, and anyone pointing to it still will
135  // cause serious harm to the Garbage Collector.
136  //
137  void* _handle;
138  T* operator& ();
139 };
140 
141 template<typename T>
142 void swap( gcroot<T> & _left,
143  gcroot<T> & _right )
144 {
145  _left.swap( _right );
146 }
147 
148 #ifndef __DEFINE_GCROOT_IN_GLOBAL_NAMESPACE
149 } // namespace msclr
150 #endif /* __DEFINE_GCROOT_IN_GLOBAL_NAMESPACE */
151 
152 #undef __GCHANDLE_TO_VOIDPTR
153 #undef __VOIDPTR_TO_GCHANDLE
154 #undef __NULLPTR
155 
156 #endif /* RC_INVOKED */
157 #endif /* !defined (_INC_MSCLR_GCROOT) */
void swap(auto_gcroot< _element_type > &_left, auto_gcroot< _element_type > &_right)
Definition: auto_gcroot.h:240
System::Runtime::InteropServices::GCHandle GCHandle
Definition: gcroot.h:58
void swap(gcroot< T > &_left, gcroot< T > &_right)
Definition: gcroot.h:142
Definition: gcroot.h:43
_CONCRTIMP void *__cdecl Alloc(size_t _NumBytes)
Allocates a block of memory of the size specified from the Concurrency Runtime Caching Suballocator...
gcroot & operator=(const gcroot &r)
Definition: gcroot.h:102
gcroot & operator=(T t)
Definition: gcroot.h:96
#define __NULLPTR
Definition: gcroot.h:48
#define __VOIDPTR_TO_GCHANDLE(x)
Definition: gcroot.h:47
Definition: gcroot.h:56
void * _handle
Definition: gcroot.h:137
#define __GCHANDLE_TO_VOIDPTR(x)
Definition: gcroot.h:46
void swap(gcroot< T > &_right)
Definition: gcroot.h:109
T operator->() const
Definition: gcroot.h:125
~gcroot()
Definition: gcroot.h:88