-
Notifications
You must be signed in to change notification settings - Fork 138
/
managedstruct.pmc
183 lines (127 loc) · 4.08 KB
/
managedstruct.pmc
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
/*
Copyright (C) 2001-2009, Parrot Foundation.
$Id$
=head1 DESCRIPTION
src/pmc/managedstruct.pmc - Memory-managed C struct
=head1 DESCRIPTION
C<ManagedStruct> extends C<UnManagedStruct> to provide a class to hold C
C<struct> values that Parrot is responsible for disposing of.
=head2 Methods
=over 4
=cut
*/
typedef void (*custom_free_func_t)(PARROT_INTERP, void *ptr, void *priv);
typedef PMC * (*custom_clone_func_t)(PARROT_INTERP, PMC *ptr, void *priv);
/* HEADERIZER HFILE: none */
/* HEADERIZER BEGIN: static */
/* HEADERIZER END: static */
pmclass ManagedStruct extends UnManagedStruct auto_attrs {
/* if custom_free_func and ptr (inherited from UnManagedStruct) are both set,
* custom_free_func is called before the normal destroy() function does any
* work.
*/
ATTR void (*custom_free_func)(PARROT_INTERP, void *, void *);
ATTR void *custom_free_priv;
/* if custom_clone_func is set, it will be called *instead* of the normal
* clone() function logic.
*/
ATTR PMC * (*custom_clone_func)(PARROT_INTERP, PMC *ptr, void *priv);
ATTR void *custom_clone_priv;
/*
=item C<void init()>
Initializes an empty struct.
=cut
*/
VTABLE void init() {
PObj_custom_destroy_SET(SELF);
}
/*
=item C<void init_pmc(PMC *value)>
Initializes the struct with C<*value>.
=cut
*/
VTABLE void init_pmc(PMC *value) {
SELF.init();
SELF.set_pmc(value);
}
/*
=item C<void destroy()>
Destroys the struct, freeing the allocated memory.
If the "custom_free_func" attribute is set, it is called to free the pointer.
Otherwise, mem_gc_free() is used.
=cut
*/
VTABLE void destroy() {
void *ptr = PARROT_MANAGEDSTRUCT(SELF)->ptr;
if (ptr) {
custom_free_func_t free_func = PARROT_MANAGEDSTRUCT(SELF)->custom_free_func;
if (free_func) {
void *free_data = PARROT_MANAGEDSTRUCT(SELF)->custom_free_priv;
free_func(INTERP, ptr, free_data);
} else
mem_gc_free(INTERP, ptr);
}
}
/*
=item C<void set_integer_native(INTVAL value)>
(Re)allocates C<value> bytes for the struct.
=cut
*/
VTABLE void set_integer_native(INTVAL value) {
Parrot_ManagedStruct_attributes * attrs = PARROT_MANAGEDSTRUCT(SELF);
if (attrs->ptr && !value) {
mem_gc_free(INTERP, attrs->ptr);
attrs->ptr = NULL;
attrs->size = 0;
}
else if (value && !attrs->ptr) {
attrs->ptr = Parrot_gc_allocate_memory_chunk_with_interior_pointers(
INTERP, (size_t)value);
attrs->size = value;
}
else if (value && attrs->ptr) {
if (attrs->size != value) {
attrs->ptr =
Parrot_gc_reallocate_memory_chunk_with_interior_pointers(INTERP,
attrs->ptr, (size_t)value, attrs->size);
attrs->size = value;
}
}
return;
}
/*
=item C<PMC * clone()>
Creates a clone of this PMC; clones any unmanaged memory it holds too.
If the "custom_clone_func" attribute is set, it is called to clone the PMC.
Otherwise, a basic (shallow copy) clone is performed, as there's no general way
of knowing how to make a deep copy of the pointer contents.
=cut
*/
VTABLE PMC *clone() {
custom_clone_func_t clone_func = PARROT_MANAGEDSTRUCT(SELF)->custom_clone_func;
PMC *dest;
if (clone_func) {
void *clone_data = PARROT_MANAGEDSTRUCT(SELF)->custom_clone_priv;
return clone_func(INTERP, SELF, clone_data);
}
dest = Parrot_pmc_new_init(INTERP, SELF->vtable->base_type,
PARROT_MANAGEDSTRUCT(SELF)->init);
if (PARROT_MANAGEDSTRUCT(SELF)->ptr)
memmove(PARROT_MANAGEDSTRUCT(dest)->ptr,
PARROT_MANAGEDSTRUCT(SELF)->ptr,
PARROT_MANAGEDSTRUCT(SELF)->size);
return dest;
}
}
/*
=back
=head1 HISTORY
Initial revision by sean 2002/08/04.
=cut
*/
/*
* Local variables:
* c-file-style: "parrot"
* End:
* vim: expandtab shiftwidth=4:
*/