e5807a1796c0b6cdfc32ee5e411fede54f956a03
[mono.git] / mono / metadata / handle.h
1 /*
2  * handle.h: Handle to object in native code
3  *
4  * Authors:
5  *  - Ludovic Henry <ludovic@xamarin.com>
6  *
7  * Copyright 2015 Xamarin, Inc. (www.xamarin.com)
8  */
9
10 #ifndef __MONO_HANDLE_H__
11 #define __MONO_HANDLE_H__
12
13 #include <config.h>
14 #include <glib.h>
15
16 #include <mono/metadata/object.h>
17 #include <mono/metadata/class.h>
18 #include <mono/utils/mono-error.h>
19 #include <mono/utils/checked-build.h>
20
21 G_BEGIN_DECLS
22
23 /*
24  * DO NOT ACCESS DIRECTLY
25  * USE mono_handle_obj BELOW TO ACCESS OBJ
26  *
27  * The field obj is not private as there is no way to do that
28  * in C, but using a C++ template would simplify that a lot
29  */
30 typedef struct {
31         MonoObject *__private_obj;
32 } MonoHandleStorage;
33
34 typedef MonoHandleStorage* MonoHandle;
35
36 typedef struct _MonoHandleArena MonoHandleArena;
37
38 gsize
39 mono_handle_arena_size (void);
40
41 MonoHandle
42 mono_handle_arena_new (MonoHandleArena *arena, MonoObject *obj);
43
44 MonoHandle
45 mono_handle_arena_elevate (MonoHandleArena *arena, MonoHandle handle);
46
47 void
48 mono_handle_arena_stack_push (MonoHandleArena **arena_stack, MonoHandleArena *arena);
49
50 void
51 mono_handle_arena_stack_pop (MonoHandleArena **arena_stack, MonoHandleArena *arena);
52
53 void
54 mono_handle_arena_init (MonoHandleArena **arena_stack);
55
56 void
57 mono_handle_arena_cleanup (MonoHandleArena **arena_stack);
58
59 MonoHandleArena*
60 mono_handle_arena_current (void);
61
62 MonoHandleArena**
63 mono_handle_arena_current_addr (void);
64
65 #define MONO_HANDLE_ARENA_PUSH()        \
66         do {    \
67                 MonoHandleArena **__arena_stack = mono_handle_arena_current_addr ();    \
68                 MonoHandleArena *__arena = (MonoHandleArena*) g_alloca (mono_handle_arena_size ());     \
69                 mono_handle_arena_stack_push (__arena_stack, __arena)
70
71 #define MONO_HANDLE_ARENA_POP() \
72                 mono_handle_arena_stack_pop (__arena_stack, __arena);   \
73         } while (0)
74
75 #define MONO_HANDLE_ARENA_POP_RETURN_UNSAFE(handle,ret) \
76                 (ret) = (handle)->__private_obj;        \
77                 mono_handle_arena_stack_pop (__arena_stack, __arena);   \
78         } while (0)
79
80 #define MONO_HANDLE_ARENA_POP_RETURN(handle,ret_handle) \
81                 *((MonoHandle**)(&(ret_handle))) = mono_handle_elevate ((MonoHandle*)(handle)); \
82                 mono_handle_arena_stack_pop(__arena_stack, __arena);    \
83         } while (0)
84
85 static inline MonoHandle
86 mono_handle_new (MonoObject *obj)
87 {
88         return mono_handle_arena_new (mono_handle_arena_current (), obj);
89 }
90
91 static inline MonoHandle
92 mono_handle_elevate (MonoHandle handle)
93 {
94         return mono_handle_arena_elevate (mono_handle_arena_current (), handle);
95 }
96
97 #ifndef ENABLE_CHECKED_BUILD
98
99 #define mono_handle_obj(handle) ((handle)->__private_obj)
100
101 #define mono_handle_assign(handle,rawptr) do { (handle)->__private_obj = (rawptr); } while(0)
102
103 #else
104
105 static inline void
106 mono_handle_check_in_critical_section ()
107 {
108         MONO_REQ_GC_CRITICAL;
109 }
110
111 #define mono_handle_obj(handle) (mono_handle_check_in_critical_section (), (handle)->__private_obj)
112
113 #define mono_handle_assign(handle,rawptr) do { mono_handle_check_in_critical_section (); (handle)->__private_obj = (rawptr); } while (0)
114
115 #endif
116
117 static inline MonoClass*
118 mono_handle_class (MonoHandle handle)
119 {
120         return mono_object_get_class (handle->__private_obj);
121 }
122
123 static inline MonoDomain*
124 mono_handle_domain (MonoHandle handle)
125 {
126         return mono_object_get_domain (handle->__private_obj);
127 }
128
129 #define mono_handle_obj_is_null(handle) ((handle)->__private_obj == NULL)
130
131 #define MONO_HANDLE_TYPE_DECL(type)      typedef struct { type *__private_obj; } type ## HandleStorage ; \
132         typedef type ## HandleStorage * type ## Handle
133 #define MONO_HANDLE_TYPE(type)           type ## Handle
134 #define MONO_HANDLE_NEW(type,obj)        ((type ## Handle) mono_handle_new ((MonoObject*) (obj)))
135 #define MONO_HANDLE_ELEVATE(type,handle) ((type ## Handle) mono_handle_elevate ((MonoObject*) (handle)->__private_obj))
136
137 #define MONO_HANDLE_ASSIGN(handle,rawptr)       \
138         do {    \
139                 mono_handle_assign ((handle), (rawptr));        \
140         } while (0)
141
142 #define MONO_HANDLE_SETREF(handle,fieldname,value)                      \
143         do {                                                            \
144                 MonoHandle __value = (MonoHandle) (value);              \
145                 MONO_PREPARE_GC_CRITICAL_REGION;                                        \
146                 MONO_OBJECT_SETREF (mono_handle_obj ((handle)), fieldname, mono_handle_obj (__value)); \
147                 MONO_FINISH_GC_CRITICAL_REGION;                                 \
148         } while (0)
149
150 #define MONO_HANDLE_SETREF_NULL(handle,fieldname)                       \
151         do {                                                            \
152                 MONO_PREPARE_GC_CRITICAL_REGION;                        \
153                 MONO_OBJECT_SETREF (mono_handle_obj ((handle)), fieldname, NULL); \
154                 MONO_FINISH_GC_CRITICAL_REGION;                         \
155         } while (0)
156
157
158 #define MONO_HANDLE_SET(handle,fieldname,value) \
159         do {    \
160                 MONO_PREPARE_GC_CRITICAL_REGION;        \
161                 mono_handle_obj ((handle))->fieldname = (value);        \
162                 MONO_FINISH_GC_CRITICAL_REGION; \
163         } while (0)
164
165 #define MONO_HANDLE_ARRAY_SETREF(handle,index,value)                    \
166         do {                                                            \
167                 MonoHandle __value = (MonoHandle) (value);              \
168                 MONO_PREPARE_GC_CRITICAL_REGION;                                        \
169                 mono_array_setref (mono_handle_obj ((handle)), (index), mono_handle_obj (__value)); \
170                 MONO_FINISH_GC_CRITICAL_REGION;                                 \
171         } while (0)
172
173 #define MONO_HANDLE_ARRAY_SETREF_NULL(handle,index)                     \
174         do {                                                            \
175                 MONO_PREPARE_GC_CRITICAL_REGION;                        \
176                 mono_array_setref (mono_handle_obj ((handle)), (index), NULL); \
177                 MONO_FINISH_GC_CRITICAL_REGION;                         \
178         } while (0)
179         
180
181 #define MONO_HANDLE_ARRAY_SET(handle,type,index,value)  \
182         do {    \
183                 MONO_PREPARE_GC_CRITICAL_REGION;        \
184                 mono_array_set (mono_handle_obj ((handle)), type, (index), (value));    \
185                 MONO_FINISH_GC_CRITICAL_REGION; \
186         } while (0)
187
188
189
190
191 /* Some common handle types */
192
193 MONO_HANDLE_TYPE_DECL (MonoArray);
194 MONO_HANDLE_TYPE_DECL (MonoString);
195
196 G_END_DECLS
197
198 #endif /* __MONO_HANDLE_H__ */