ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
(Generate patch)

Comparing deliantra/server/server/cfperl.xs (file contents):
Revision 1.148 by root, Sat Jan 20 23:39:09 2007 UTC vs.
Revision 1.160 by elmex, Wed Jan 31 14:11:02 2007 UTC

102unordered_vector<attachable *> attachable::mortals; 102unordered_vector<attachable *> attachable::mortals;
103 103
104attachable::~attachable () 104attachable::~attachable ()
105{ 105{
106 assert (!self); 106 assert (!self);
107 assert (!cb);
107} 108}
108 109
109int 110int
110attachable::refcnt_cnt () const 111attachable::refcnt_cnt () const
111{ 112{
112 return refcnt + (self ? SvREFCNT (self) : 0); 113 return refcnt + (self ? SvREFCNT (self) - 1 : 0);
114}
115
116void
117attachable::sever_self ()
118{
119 if (HV *self = this->self)
120 {
121 // keep a refcount because sv_unmagic might call attachable_free,
122 // which might clear self, causing sv_unmagic to crash on a now
123 // invalid object.
124 SvREFCNT_inc (self);
125 hv_clear (self);
126 sv_unmagic ((SV *)self, PERL_MAGIC_ext);
127 SvREFCNT_dec (self);
128
129 // self *must* be null now because thats sv_unmagic's job.
130 assert (!this->self);
131 }
113} 132}
114 133
115void 134void
116attachable::optimise () 135attachable::optimise ()
117{ 136{
118 if (self 137 if (self
119 && SvREFCNT (self) == 1 138 && SvREFCNT (self) == 1
120 && !HvTOTALKEYS (self)) 139 && !HvTOTALKEYS (self))
140 sever_self ();
141}
142
143// check wether the object really is dead
144void
145attachable::do_check ()
146{
147 if (refcnt_cnt () > 0)
148 return;
149
150 destroy ();
151}
152
153void
154attachable::do_destroy ()
155{
156 invoke (EVENT_ATTACHABLE_DESTROY, DT_END);
157
158 if (cb)
121 { 159 {
122 refcnt_inc ();
123 SvREFCNT_dec ((SV *)self); 160 SvREFCNT_dec (cb);
161 cb = 0;
124 } 162 }
125}
126
127// check wether the object really is dead
128void
129attachable::do_check ()
130{
131 if (refcnt > 0 || refcnt_cnt () > 0)
132 return;
133
134 destroy ();
135 163
136 if (self) 164 if (self)
137 { 165 sever_self ();
138 hv_clear (self);
139 sv_unmagic ((SV *)self, PERL_MAGIC_ext);
140 SvREFCNT_dec (self);
141 self = 0;
142 }
143}
144
145void
146attachable::do_destroy ()
147{
148 invoke (EVENT_ATTACHABLE_DESTROY, DT_END);
149
150 if (self)
151 hv_clear (self);
152 166
153 mortals.push_back (this); 167 mortals.push_back (this);
154} 168}
155 169
156void 170void
164} 178}
165 179
166void 180void
167attachable::check_mortals () 181attachable::check_mortals ()
168{ 182{
169 for (int i = 0; i < mortals.size (); ) 183 static int i = 0;
184
185 for (;;)
170 { 186 {
187 if (i >= mortals.size ())
188 {
189 i = 0;
190
191 if (mortals.size () > 1000)
192 fprintf (stderr, "mortal queue size (%d) exceeds 1000.\n", (int)mortals.size ());
193
194 break;
195 }
196
171 attachable *obj = mortals [i]; 197 attachable *obj = mortals [i];
172 198
173 obj->refcnt_chk (); // unborrow from perl, if necessary 199 obj->refcnt_chk (); // unborrow from perl, if necessary
174 200
201 //if (obj->refcnt > 0 || obj->self)
175 if (obj->refcnt || obj->self) 202 if (obj->refcnt || obj->self)
176 { 203 {
177#if 0 204//printf ("%p rc %d\n", obj, obj->refcnt_cnt ());//D
178 if (mortals.size() > 5)fprintf (stderr, "%d delaying %d:%p:%s %d (self %p:%d)\n", time(0),i, obj, typeid (*obj).name (),
179 obj->refcnt, obj->self, obj->self ? SvREFCNT(obj->self): - 1);//D
180#endif
181
182 ++i; // further delay freeing 205 ++i; // further delay freeing
206
207 if (!(i & 0x3ff))
208 break;
183 }//D 209 }
184 else 210 else
185 { 211 {
186 //Dfprintf (stderr, "deleteing %d:%p:%s\n", i, obj,typeid (*obj).name ());//D
187 mortals.erase (i); 212 mortals.erase (i);
188 delete obj; 213 delete obj;
189 } 214 }
190 } 215 }
191} 216}
216 241
217static int 242static int
218attachable_free (pTHX_ SV *sv, MAGIC *mg) 243attachable_free (pTHX_ SV *sv, MAGIC *mg)
219{ 244{
220 attachable *at = (attachable *)mg->mg_ptr; 245 attachable *at = (attachable *)mg->mg_ptr;
246
247 //TODO: check if transaction behaviour is really required here
248 if (SV *self = (SV *)at->self)
249 {
221 at->self = 0; 250 at->self = 0;
251 SvREFCNT_dec (self);
252 }
253
222 // next line makes sense, but most objects still have refcnt 0 by default 254 // next line makes sense, but most objects still have refcnt 0 by default
223 //at->refcnt_chk (); 255 //at->refcnt_chk ();
224 return 0; 256 return 0;
225} 257}
226 258
234 266
235 if (!obj->self) 267 if (!obj->self)
236 { 268 {
237 obj->self = newHV (); 269 obj->self = newHV ();
238 sv_magicext ((SV *)obj->self, 0, PERL_MAGIC_ext, &attachable::vtbl, (char *)obj, 0); 270 sv_magicext ((SV *)obj->self, 0, PERL_MAGIC_ext, &attachable::vtbl, (char *)obj, 0);
239
240 // borrow the refcnt from the object
241 // it is important thta no refcnt_chk is being executed here
242 obj->refcnt_dec ();
243 271
244 // now bless the object _once_ 272 // now bless the object _once_
245 return sv_bless (newRV_inc ((SV *)obj->self), stash); 273 return sv_bless (newRV_inc ((SV *)obj->self), stash);
246 } 274 }
247 else 275 else
319inline SV *to_sv (treasurelist * v) { return to_sv (v->name); } 347inline SV *to_sv (treasurelist * v) { return to_sv (v->name); }
320 348
321inline SV *to_sv (UUID v) 349inline SV *to_sv (UUID v)
322{ 350{
323 char buf[128]; 351 char buf[128];
324 snprintf (buf, 128, "<1,%" PRIx64 ">", v.seq); 352 snprintf (buf, 128, "<1.%" PRIx64 ">", v.seq);
325 return newSVpv (buf, 0); 353 return newSVpv (buf, 0);
326} 354}
327 355
328inline void sv_to (SV *sv, shstr &v) { v = SvOK (sv) ? SvPV_nolen (sv) : 0; } 356inline void sv_to (SV *sv, shstr &v) { v = SvOK (sv) ? SvPV_nolen (sv) : 0; }
329inline void sv_to (SV *sv, char * &v) { free (v); v = SvOK (sv) ? strdup (SvPV_nolen (sv)) : 0; } 357inline void sv_to (SV *sv, char * &v) { free (v); v = SvOK (sv) ? strdup (SvPV_nolen (sv)) : 0; }
895void 923void
896iw::alloc () 924iw::alloc ()
897{ 925{
898 pe = GEventAPI->new_idle (0, 0); 926 pe = GEventAPI->new_idle (0, 0);
899 927
928 WaREENTRANT_off (pe);
900 pe->base.callback = (void *)iw_dispatch; 929 pe->base.callback = (void *)iw_dispatch;
901 pe->base.ext_data = (void *)this; 930 pe->base.ext_data = (void *)this;
902} 931}
903 932
904static void iow_dispatch (pe_event *ev) 933static void iow_dispatch (pe_event *ev)
910void 939void
911iow::alloc () 940iow::alloc ()
912{ 941{
913 pe = GEventAPI->new_io (0, 0); 942 pe = GEventAPI->new_io (0, 0);
914 943
944 WaREENTRANT_off (pe);
915 pe->base.callback = (void *)iow_dispatch; 945 pe->base.callback = (void *)iow_dispatch;
916 pe->base.ext_data = (void *)this; 946 pe->base.ext_data = (void *)this;
917 947
918 pe->fd = -1; 948 pe->fd = -1;
919 pe->poll = 0; 949 pe->poll = 0;
1619 1649
1620void cleanup (const char *cause, bool make_core = false) 1650void cleanup (const char *cause, bool make_core = false)
1621 1651
1622void emergency_save () 1652void emergency_save ()
1623 1653
1624void _exit (int status = 0) 1654void _exit (int status = EXIT_SUCCESS)
1655
1656UV sv_2watcher (SV *w)
1657 CODE:
1658 RETVAL = (UV)GEventAPI->sv_2watcher (w);
1659 OUTPUT:
1660 RETVAL
1625 1661
1626#if _POSIX_MEMLOCK 1662#if _POSIX_MEMLOCK
1627 1663
1628int mlockall (int flags = MCL_CURRENT | MCL_FUTURE) 1664int mlockall (int flags = MCL_CURRENT | MCL_FUTURE)
1629 1665
1684 CODE: 1720 CODE:
1685 RETVAL = SvROK (obj) && mg_find (SvRV (obj), PERL_MAGIC_ext); 1721 RETVAL = SvROK (obj) && mg_find (SvRV (obj), PERL_MAGIC_ext);
1686 OUTPUT: 1722 OUTPUT:
1687 RETVAL 1723 RETVAL
1688 1724
1725int mortals_size ()
1726 CODE:
1727 RETVAL = attachable::mortals.size ();
1728 OUTPUT: RETVAL
1729
1730#object *mortals (U32 index)
1731# CODE:
1732# RETVAL = index < attachable::mortals.size () ? attachable::mortals [index] : 0;
1733# OUTPUT: RETVAL
1734
1689INCLUDE: $PERL genacc attachable ../include/cfperl.h | 1735INCLUDE: $PERL genacc attachable ../include/cfperl.h |
1690 1736
1691MODULE = cf PACKAGE = cf::global 1737MODULE = cf PACKAGE = cf::global
1692 1738
1693int invoke (SV *klass, int event, ...) 1739int invoke (SV *klass, int event, ...)
1710 RETVAL = op->invoke ((event_type)event, ARG_AV (av), DT_END); 1756 RETVAL = op->invoke ((event_type)event, ARG_AV (av), DT_END);
1711 OUTPUT: RETVAL 1757 OUTPUT: RETVAL
1712 1758
1713SV *registry (object *op) 1759SV *registry (object *op)
1714 1760
1715void mortals ()
1716 PPCODE:
1717 EXTEND (SP, object::mortals.size ());
1718 for (AUTODECL (i, object::mortals.begin ()); i != object::mortals.end (); ++i)
1719 PUSHs (to_sv (*i));
1720
1721int objects_size () 1761int objects_size ()
1722 CODE: 1762 CODE:
1723 RETVAL = objects.size (); 1763 RETVAL = objects.size ();
1724 OUTPUT: RETVAL 1764 OUTPUT: RETVAL
1725 1765
1764 1804
1765void 1805void
1766set_animation (object *op, int idx) 1806set_animation (object *op, int idx)
1767 CODE: 1807 CODE:
1768 SET_ANIMATION (op, idx); 1808 SET_ANIMATION (op, idx);
1809
1810int
1811num_animations (object *op)
1812 CODE:
1813 RETVAL = NUM_ANIMATIONS (op);
1814 OUTPUT: RETVAL
1769 1815
1770object *find_best_object_match (object *op, const char *match) 1816object *find_best_object_match (object *op, const char *match)
1771 1817
1772object *find_marked_object (object *op) 1818object *find_marked_object (object *op)
1773 1819
2101 EXTEND (SP, THIS->players); 2147 EXTEND (SP, THIS->players);
2102 for_all_players (pl) 2148 for_all_players (pl)
2103 if (pl->ob && pl->ob->map == THIS) 2149 if (pl->ob && pl->ob->map == THIS)
2104 PUSHs (sv_2mortal (to_sv (pl->ob))); 2150 PUSHs (sv_2mortal (to_sv (pl->ob)));
2105 } 2151 }
2152
2153void
2154maptile::set_regiondata (SV *data, SV *plt)
2155 CODE:
2156{
2157 if (!SvROK (plt) || SvTYPE (SvRV (plt)) != SVt_PVAV)
2158 croak ("maptile::set_regiondata needs arrayref as plt arg");
2159
2160 AV *av = (AV *)SvRV (plt);
2161
2162 region **regionmap = (region **)malloc ((av_len (av) + 1) * sizeof (region *));
2163
2164 for (int i = av_len (av) + 1; i--; )
2165 regionmap [i] = region::find (SvPVutf8_nolen (*av_fetch (av, i, 1)));
2166
2167 THIS->regions = salloc<uint8_t> (THIS->size (), (uint8_t *)SvPVbyte_nolen (data));
2168 THIS->regionmap = regionmap;
2169}
2106 2170
2107void play_sound_map (maptile *map, int x, int y, int sound_num) 2171void play_sound_map (maptile *map, int x, int y, int sound_num)
2108 2172
2109int out_of_map (maptile *map, int x, int y) 2173int out_of_map (maptile *map, int x, int y)
2110 2174
2191 OUTPUT: RETVAL 2255 OUTPUT: RETVAL
2192 2256
2193void fix_walls (maptile *map, int x, int y) 2257void fix_walls (maptile *map, int x, int y)
2194 2258
2195void fix_walls_around (maptile *map, int x, int y) 2259void fix_walls_around (maptile *map, int x, int y)
2196
2197const char *
2198region_name (maptile *m)
2199 CODE:
2200 RETVAL = get_name_of_region_for_map (m);
2201 OUTPUT: RETVAL
2202 2260
2203# worst xs function of my life 2261# worst xs function of my life
2204bool 2262bool
2205_create_random_map (\ 2263_create_random_map (\
2206 maptile *self,\ 2264 maptile *self,\
2323 OUTPUT: RETVAL 2381 OUTPUT: RETVAL
2324 2382
2325region *find (char *name) 2383region *find (char *name)
2326 PROTOTYPE: $ 2384 PROTOTYPE: $
2327 CODE: 2385 CODE:
2328 RETVAL = get_region_by_name (name); 2386 RETVAL = region::find (name);
2329 OUTPUT: RETVAL 2387 OUTPUT: RETVAL
2330 2388
2331INCLUDE: $PERL genacc region ../include/map.h | 2389INCLUDE: $PERL genacc region ../include/map.h |
2332 2390
2333MODULE = cf PACKAGE = cf::living 2391MODULE = cf PACKAGE = cf::living

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines