1/* 2Copyright (C) 2011-2014, Parrot Foundation. 3 4=head1 NAME 5 6src/pmc/ptrobj.pmc - PtrObj PMC 7 8=head1 DESCRIPTION 9 10C<PtrObj> is for object-ish pointers. These augment C<PtrBuf> to afford 11memory management. 12 13=head2 VTABLEs 14 15=over 4 16 17=cut 18 19*/ 20 21/* HEADERIZER HFILE: none */ 22/* HEADERIZER BEGIN: static */ 23/* HEADERIZER END: static */ 24 25BEGIN_PMC_HEADER_PREAMBLE 26typedef PMC *(*ptrobj_clone_func_t)(PARROT_INTERP, ARGIN(PMC *), ARGIN(void *)); 27typedef void (*ptrobj_mark_func_t)(PARROT_INTERP, ARGIN(PMC *), ARGIN(void *)); 28typedef void (*ptrobj_destroy_func_t)(PARROT_INTERP, ARGIN(PMC *), ARGIN(void *)); 29 30#define PTROBJ_SET_CLONE(i, p, c) do { \ 31 SETATTR_PtrObj_clone((i), (p), (c)); \ 32} while (0) 33 34#define PTROBJ_SET_MARK(i, p, m) do { \ 35 SETATTR_PtrObj_mark((i), (p), (m)); \ 36 if (m) \ 37 PObj_custom_mark_SET(p); \ 38 else \ 39 PObj_custom_mark_CLEAR(p); \ 40} while (0) 41 42#define PTROBJ_SET_DESTROY(i, p, d) do { \ 43 SETATTR_PtrObj_destroy((i), (p), (d)); \ 44 if (d) \ 45 PObj_custom_destroy_SET(p); \ 46 else \ 47 PObj_custom_destroy_CLEAR(p); \ 48} while (0) 49END_PMC_HEADER_PREAMBLE 50 51pmclass PtrObj extends PtrBuf auto_attrs { 52 ATTR ptrobj_clone_func_t clone; 53 ATTR ptrobj_mark_func_t mark; 54 ATTR ptrobj_destroy_func_t destroy; 55 56/* 57 58=item C<PMC *clone()> 59 60Invoke the custom C<clone> function, if one has been provided. Otherwise, cloning is an error. 61 62=item C<METHOD clone_func(func :optional)> 63 64Get or set the custom C<clone> function. 65 66=cut 67 68*/ 69 70 71 VTABLE PMC *clone() :no_wb { 72 void *ptr; 73 ptrobj_clone_func_t clone; 74 GET_ATTR_ptr(INTERP, SELF, ptr); 75 GET_ATTR_clone(INTERP, SELF, clone); 76 if (clone) 77 return clone(INTERP, SELF, ptr); 78 else 79 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_METHOD_NOT_FOUND, 80 "clone not implemented for PtrObj %p", ptr); 81 } 82 83 METHOD clone_func(PMC *func :optional, INTVAL has_func :opt_flag) :manual_wb { 84 if (has_func) { 85 void * const f = VTABLE_get_pointer(INTERP, func); 86 PTROBJ_SET_CLONE(INTERP, SELF, (ptrobj_clone_func_t)f); 87 PARROT_GC_WRITE_BARRIER(INTERP, SELF); 88 RETURN(); 89 } 90 else { 91 ptrobj_clone_func_t f; 92 GET_ATTR_clone(INTERP, SELF, f); 93 func = Parrot_pmc_new_init_int(INTERP, enum_class_Ptr, PTR2INTVAL(f)); 94 RETURN(PMC func); 95 } 96 } 97 98/* 99 100=item C<void mark()> 101 102Invoke the custom C<mark> function, if one has been provided. 103 104=item C<METHOD mark_func(func :optional)> 105 106Get or set the custom C<mark> function. 107 108=cut 109 110*/ 111 112 VTABLE void mark() :no_wb { 113 void *ptr; 114 ptrobj_mark_func_t mark; 115 GET_ATTR_ptr(INTERP, SELF, ptr); 116 GET_ATTR_mark(INTERP, SELF, mark); 117 /* invariant: custom mark flag only set when a custom mark function has been provided */ 118 PARROT_ASSERT(mark); 119 mark(INTERP, SELF, ptr); 120 } 121 122 METHOD mark_func(PMC *func :optional, INTVAL has_func :opt_flag) :manual_wb { 123 if (has_func) { 124 void * const f = VTABLE_get_pointer(INTERP, func); 125 PTROBJ_SET_MARK(INTERP, SELF, (ptrobj_mark_func_t)f); 126 PARROT_GC_WRITE_BARRIER(INTERP, SELF); 127 RETURN(); 128 } 129 else { 130 ptrobj_mark_func_t f; 131 GET_ATTR_mark(INTERP, SELF, f); 132 func = Parrot_pmc_new_init_int(INTERP, enum_class_Ptr, PTR2ULONG(f)); 133 RETURN(PMC func); 134 } 135 } 136 137/* 138 139=item C<void destroy()> 140 141Invoke the custom C<destroy> function if one has been provided. 142 143=item C<METHOD destroy_func(func :optional)> 144 145Get or set the custom C<destroy> function. 146 147=cut 148 149*/ 150 151 VTABLE void destroy() :no_wb { 152 void *ptr; 153 ptrobj_destroy_func_t destroy; 154 GET_ATTR_ptr(INTERP, SELF, ptr); 155 GET_ATTR_destroy(INTERP, SELF, destroy); 156 /* invariant: custom destroy flag only set when a destroy function has been provided */ 157 PARROT_ASSERT(destroy); 158 destroy(INTERP, SELF, ptr); 159 } 160 161 METHOD destroy_func(PMC *func :optional, INTVAL has_func :opt_flag) :manual_wb { 162 if (has_func) { 163 void * const f = VTABLE_get_pointer(INTERP, func); 164 PTROBJ_SET_DESTROY(INTERP, SELF, (ptrobj_destroy_func_t)f); 165 PARROT_GC_WRITE_BARRIER(INTERP, SELF); 166 RETURN(); 167 } 168 else { 169 ptrobj_destroy_func_t f; 170 GET_ATTR_destroy(INTERP, SELF, f); 171 func = Parrot_pmc_new_init_int(INTERP, enum_class_Ptr, PTR2ULONG(f)); 172 RETURN(PMC func); 173 } 174 } 175} 176 177/* 178 179=back 180 181=cut 182 183*/ 184 185/* 186 * Local variables: 187 * c-file-style: "parrot" 188 * End: 189 * vim: expandtab shiftwidth=4 cinoptions='\:2=2' : 190 */ 191