tagged release 0.6.4
[parrot.git] / src / pmc / addrregistry.pmc
blob73f0d57483cc395a6b450fe9181e8b4cf8da8421
1 /*
2 Copyright (C) 2005-2008, The Perl Foundation.
3 $Id$
5 =head1 NAME
7 src/pmc/addrregistry.pmc - A DOD Registry PMC
9 =head1 DESCRIPTION
11 The AddrRegistry class provides the equivalence of reference counts
12 mainly for extenders and embedders of Parrot. The hash keys are the
13 addresses of the key PMC, values are reference counts, i.e. the
14 difference of (set_pmc_keyed - delete_pmc_keyed). If the reference
15 goes to zero, the entry is deleted physically.
17 Please note that you have to anchor an instance of AddrRegistry yourself with
18 C<Parrot_register_pmc> if it isn't visible to Parrot.
20 =head2 Functions
22 =over 4
24 =cut
28 #include "parrot/parrot.h"
30 /* included manually to prevent breaking C++ builds -- see RT #56534 */
31 #include "parrot/hash.h"
32 #include "pmc_hash.h"
34 pmclass AddrRegistry need_ext provides hash {
35     ATTR Hash *hash;    /* a PMC Hash */
38 =item C<void init()>
40 Initializes the instance.
42 =item C<void destroy()>
44 Free hash structure.
46 =cut
50     VTABLE void init() {
51         Hash                       *registry;
52         Parrot_AddrRegistry * const addr_registry =
53             mem_allocate_zeroed_typed(Parrot_AddrRegistry);
55         PMC_data(SELF)      = addr_registry;
56         PObj_custom_mark_destroy_SETALL(SELF);
58         parrot_new_pmc_hash_x(SELF, enum_type_int, Hash_key_type_PMC,
59                               int_compare, key_hash_int);
61         registry            = (Hash*)PMC_struct_val(SELF);
63         /* this hack can go away when parrot_new_pmc_hash_x behaves */
64         addr_registry->hash = registry;
65         registry->container = SELF;
66     }
68     VTABLE void destroy() {
69         if (PMC_data(SELF)) {
70             Parrot_AddrRegistry * const registry = PARROT_ADDRREGISTRY(SELF);
72             parrot_hash_destroy(INTERP, registry->hash);
73             PMC_data(SELF) = NULL;
74         }
75     }
79 =item C<void mark()>
81 Marks the hash as live.
83 =cut
87     VTABLE void mark() {
88         if (PMC_data(SELF))
89             parrot_mark_hash(INTERP, PARROT_ADDRREGISTRY(SELF)->hash);
90     }
94 =item C<INTVAL get_integer_keyed(PMC *key)>
96 Returns the reference count for C<key> or 0 if the key doesn't exist.
98 =item C<INTVAL elements()>
100 Returns the number of elements in the hash.
102 =item C<INTVAL get_bool()>
104 Returns true if the hash size is not zero.
106 =cut
110     VTABLE INTVAL get_integer_keyed(PMC *key) {
111         Hash   *hash  = PARROT_ADDRREGISTRY(SELF)->hash;
112         void   *value = parrot_hash_get(INTERP, hash, key);
114         if (value)
115             return (INTVAL)value;
117         return 0;
118     }
120     VTABLE INTVAL elements() {
121         return parrot_hash_size(INTERP, PARROT_ADDRREGISTRY(SELF)->hash);
122     }
124     VTABLE INTVAL get_bool() {
125         return parrot_hash_size(INTERP, PARROT_ADDRREGISTRY(SELF)->hash) != 0;
126     }
129 =item C<void set_pmc_keyed(PMC *key, PMC *value)>
131 Increment the reference count of C<key>. If the entry doesn't exist
132 create it. The C<value> is always ignored.
134 =item C<void set_integer_keyed(PMC *key, INTVAL value)>
136 Set the given value.
138 =item C<void delete_keyed(PMC *key)>
140 Decrement the reference count of C<key>. If the reference count
141 reaches 0, delete the entry.
144 =cut
148     VTABLE void set_pmc_keyed(PMC *key, PMC *value) {
149         Hash       * const hash = PARROT_ADDRREGISTRY(SELF)->hash;
150         void       *oldval      = parrot_hash_get(INTERP, hash, key);
151         long        newval      = 1;
152         UNUSED(value);
154         if (oldval)
155             newval += (long)oldval;
157         parrot_hash_put(INTERP, hash, key, (void *)newval);
158     }
160     VTABLE void set_integer_keyed(PMC *key, INTVAL value) {
161         Hash *hash = PARROT_ADDRREGISTRY(SELF)->hash;
162         parrot_hash_put(INTERP, hash, key, (void *)value);
163     }
165     VTABLE void delete_keyed(PMC *key) {
166         Hash       * const hash  = PARROT_ADDRREGISTRY(SELF)->hash;
167         void              *value = parrot_hash_get(INTERP, hash, key);
169         /* these casts look bad, but they avoid type punning warnings with -O */
170         if (value) {
171             long val = (long)value;
172             if (val == 1L)
173                 parrot_hash_delete(INTERP, hash, key);
174             else {
175                 value = (void *)(--val);
176                 parrot_hash_put(INTERP, hash, key, value);
177             }
178         }
179     }
183 =item C<PMC *get_iter ()>
185 Return a new iterator for the PMC.
187 =item C<PMC *get_pmc_keyed(PMC *key)>
189 If called from iteration, return the key PMC, else PMCNULL is returned.
191 =cut
195     VTABLE PMC *get_iter() {
196         return Parrot_Hash_get_iter(INTERP, SELF);
197     }
199     VTABLE PMC *get_pmc_keyed(PMC *key) {
200         Hash * const hash = PARROT_ADDRREGISTRY(SELF)->hash;
202         if (KEY_IS_HASH_ITERATOR(key))
203             return (PMC *)parrot_hash_get_idx(INTERP, hash, key);
205         return PMCNULL;
206     }
211 =back
213 =head1 SEE ALSO
215 F<src/pmc.c:dod_register_pmc()>
217 =cut
222  * Local variables:
223  *   c-file-style: "parrot"
224  * End:
225  * vim: expandtab shiftwidth=4:
226  */