9263825572765571a4e6806dd85e6ea6552ff5b5
[p5sagit/p5-mst-13.2.git] / ext / threads / shared / shared.xs
1
2 #include "EXTERN.h"
3 #include "perl.h"
4 #include "XSUB.h"
5
6
7 void shared_sv_attach_sv (SV* sv, shared_sv* shared) {
8     HV* shared_hv = get_hv("threads::shared::shared", FALSE);
9     SV* id = newSViv((IV)shared);
10     STRLEN length = sv_len(id);
11     SV* tiedobject;
12     SV** tiedobject_ = hv_fetch(shared_hv, SvPV(id,length), length, 0);
13     if(tiedobject_) {
14         tiedobject = (*tiedobject_);
15         SvROK_on(sv);
16         SvRV(sv) = SvRV(tiedobject);
17
18     } else {
19         croak("die\n");
20     }
21 }
22
23
24 int shared_sv_fetch_mg (pTHX_ SV* sv, MAGIC *mg) {
25     shared_sv* shared = (shared_sv*) SvIV(mg->mg_obj);
26     SHAREDSvLOCK(shared);
27     if(mg->mg_private != shared->index) {
28         if(SvROK(SHAREDSvGET(shared))) {
29             shared_sv* target = (shared_sv*) SvIV(SvRV(SHAREDSvGET(shared)));
30             shared_sv_attach_sv(sv, target);
31         } else {
32             sv_setsv(sv, SHAREDSvGET(shared));
33         }
34         mg->mg_private = shared->index;
35     }
36     SHAREDSvUNLOCK(shared);
37
38     return 0;
39 }
40
41 int shared_sv_store_mg (pTHX_ SV* sv, MAGIC *mg) {
42     shared_sv* shared = (shared_sv*) SvIV(mg->mg_obj);
43     SHAREDSvLOCK(shared);
44     if(SvROK(SHAREDSvGET(shared)))
45         Perl_sharedsv_thrcnt_dec(aTHX_ (shared_sv*) SvIV(SvRV(SHAREDSvGET(shared))));
46     SHAREDSvEDIT(shared);
47     if(SvROK(sv)) {
48         shared_sv* target = Perl_sharedsv_find(aTHX_ SvRV(sv));
49         if(!target) {
50             SHAREDSvRELEASE(shared);
51             sv_setsv(sv,SHAREDSvGET(shared));
52             SHAREDSvUNLOCK(shared);            
53             Perl_croak(aTHX_ "You cannot assign a non shared reference to a shared scalar");
54         }
55         Perl_sv_free(PL_sharedsv_space,SHAREDSvGET(shared));
56         SHAREDSvGET(shared) = newRV_noinc(newSViv((IV)target));
57     } else {
58         sv_setsv(SHAREDSvGET(shared), sv);
59     }
60     shared->index++;
61     mg->mg_private = shared->index;
62     SHAREDSvRELEASE(shared);
63     if(SvROK(SHAREDSvGET(shared)))
64        Perl_sharedsv_thrcnt_inc(aTHX_ (shared_sv*) SvIV(SvRV(SHAREDSvGET(shared))));       
65     SHAREDSvUNLOCK(shared);
66     return 0;
67 }
68
69 int shared_sv_destroy_mg (pTHX_ SV* sv, MAGIC *mg) {
70     shared_sv* shared = (shared_sv*) SvIV(mg->mg_obj);
71     if(!shared) 
72         return 0;
73     Perl_sharedsv_thrcnt_dec(aTHX_ shared);
74 }
75
76 MGVTBL svtable = {MEMBER_TO_FPTR(shared_sv_fetch_mg),
77                   MEMBER_TO_FPTR(shared_sv_store_mg),
78                   0,
79                   0,
80                   MEMBER_TO_FPTR(shared_sv_destroy_mg)
81 };
82
83 MODULE = threads::shared                PACKAGE = threads::shared               
84
85
86 PROTOTYPES: DISABLE
87
88
89 SV*
90 ptr(ref)
91         SV* ref
92         CODE:
93         RETVAL = newSViv(SvIV(SvRV(ref)));
94         OUTPUT:
95         RETVAL
96
97
98 SV*
99 _thrcnt(ref)
100         SV* ref
101         CODE:
102         shared_sv* shared = Perl_sharedsv_find(aTHX, ref);
103         if(!shared)
104            croak("thrcnt can only be used on shared values");
105         SHAREDSvLOCK(shared);
106         RETVAL = newSViv(SvREFCNT(SHAREDSvGET(shared)));
107         SHAREDSvUNLOCK(shared);
108         OUTPUT:
109         RETVAL   
110
111
112 void
113 thrcnt_inc(ref)
114         SV* ref
115         CODE:
116         shared_sv* shared;
117         if(SvROK(ref)) 
118             ref = SvRV(ref);
119         shared = Perl_sharedsv_find(aTHX, ref);
120         if(!shared)
121            croak("thrcnt can only be used on shared values");
122         Perl_sharedsv_thrcnt_inc(aTHX_ shared);
123
124
125 MODULE = threads::shared                PACKAGE = threads::shared::sv           
126
127 SV*
128 new(class, value)
129         SV* class
130         SV* value
131         CODE:
132         shared_sv* shared = Perl_sharedsv_new(aTHX);
133         MAGIC* shared_magic;
134         SV* obj = newSViv((IV)shared);
135         SHAREDSvEDIT(shared);
136         SHAREDSvGET(shared) = newSVsv(value);
137         SHAREDSvRELEASE(shared);
138         sv_magic(value, 0, PERL_MAGIC_ext, "threads::shared", 16);
139         shared_magic = mg_find(value, PERL_MAGIC_ext);
140         shared_magic->mg_virtual = &svtable;
141         shared_magic->mg_obj = newSViv((IV)shared);
142         shared_magic->mg_flags |= MGf_REFCOUNTED;
143         shared_magic->mg_private = 0;
144         SvMAGICAL_on(value);
145         RETVAL = obj;
146         OUTPUT:         
147         RETVAL
148
149
150 MODULE = threads::shared                PACKAGE = threads::shared::av
151
152 SV* 
153 new(class, value)
154         SV* class
155         SV* value
156         CODE:
157         shared_sv* shared = Perl_sharedsv_new(aTHX);
158         SV* obj = newSViv((IV)shared);
159         SHAREDSvEDIT(shared);
160         SHAREDSvGET(shared) = (SV*) newAV();
161         SHAREDSvRELEASE(shared);
162         RETVAL = obj;
163         OUTPUT:
164         RETVAL
165
166 void
167 STORE(self, index, value)
168         SV* self
169         SV* index
170         SV* value
171         CODE:    
172         shared_sv* shared = (shared_sv*) SvIV(SvRV(self));
173         shared_sv* slot;
174         SV* aentry;
175         SV** aentry_;
176         SHAREDSvLOCK(shared);
177         aentry_ = av_fetch((AV*) SHAREDSvGET(shared), SvIV(index), 0);
178         if(aentry_ && SvIV((*aentry_))) {
179             aentry = (*aentry_);
180             slot = (shared_sv*) SvIV(aentry);
181             if(SvROK(SHAREDSvGET(slot)))
182                 Perl_sharedsv_thrcnt_dec(aTHX_ (shared_sv*) SvIV(SvRV(SHAREDSvGET(slot))));
183             SHAREDSvEDIT(slot);
184             sv_setsv(SHAREDSvGET(slot), value);
185             SHAREDSvRELEASE(slot);
186         } else {
187             slot = Perl_sharedsv_new(aTHX);
188             SHAREDSvEDIT(shared);
189             SHAREDSvGET(slot) = newSVsv(value);
190             aentry = newSViv((IV)slot);
191             av_store((AV*) SHAREDSvGET(shared), SvIV(index), aentry);
192             SHAREDSvRELEASE(shared);
193         }
194         SHAREDSvUNLOCK(shared);
195
196 SV*
197 FETCH(self, index)
198         SV* self
199         SV* index
200         CODE:
201         shared_sv* shared = (shared_sv*) SvIV(SvRV(self));
202         shared_sv* slot;
203         SV* aentry;
204         SV** aentry_;
205         SV* retval;
206         SHAREDSvLOCK(shared);
207         aentry_ = av_fetch((AV*) SHAREDSvGET(shared), SvIV(index),0);
208         if(aentry_) {
209             aentry = (*aentry_);
210             if(SvTYPE(aentry) == SVt_NULL) {
211                 retval = &PL_sv_undef;
212             } else {
213                 slot = (shared_sv*) SvIV(aentry);
214                 retval = newSVsv(SHAREDSvGET(slot));
215             }
216         } else {
217             retval = &PL_sv_undef;
218         }
219         SHAREDSvUNLOCK(shared); 
220         RETVAL = retval;
221         OUTPUT:
222         RETVAL
223
224 void
225 PUSH(self, ...)
226         SV* self
227         CODE:
228         shared_sv* shared = (shared_sv*) SvIV(SvRV(self));
229         int i;
230         SHAREDSvLOCK(shared);
231         for(i = 1; i < items; i++) {
232             shared_sv* slot = Perl_sharedsv_new(aTHX);
233             SV* tmp = ST(i);
234             SHAREDSvEDIT(slot);
235             SHAREDSvGET(slot) = newSVsv(tmp);
236             av_push((AV*) SHAREDSvGET(shared), newSViv((IV)slot));          
237             SHAREDSvRELEASE(slot);
238         }
239         SHAREDSvUNLOCK(shared);
240
241 void
242 UNSHIFT(self, ...)
243         SV* self
244         CODE:
245         shared_sv* shared = (shared_sv*) SvIV(SvRV(self));
246         int i;
247         SHAREDSvLOCK(shared);
248         SHAREDSvEDIT(shared);
249         av_unshift((AV*)SHAREDSvGET(shared), items - 1);
250         SHAREDSvRELEASE(shared);
251         for(i = 1; i < items; i++) {
252             shared_sv* slot = Perl_sharedsv_new(aTHX);
253             SV* tmp = ST(i);
254             SHAREDSvEDIT(slot);
255             SHAREDSvGET(slot) = newSVsv(tmp);
256             av_store((AV*) SHAREDSvGET(shared), i - 1, newSViv((IV)slot));
257             SHAREDSvRELEASE(slot);
258         }
259         SHAREDSvUNLOCK(shared);
260
261 SV*
262 POP(self)
263         SV* self
264         CODE:
265         shared_sv* shared = (shared_sv*) SvIV(SvRV(self));
266         shared_sv* slot;
267         SV* retval;
268         SHAREDSvLOCK(shared);
269         SHAREDSvEDIT(shared);
270         retval = av_pop((AV*)SHAREDSvGET(shared));
271         SHAREDSvRELEASE(shared);
272         if(retval && SvIV(retval)) {
273             slot = (shared_sv*) SvIV(retval);
274             retval = newSVsv(SHAREDSvGET(slot));
275             Perl_sharedsv_thrcnt_dec(aTHX_ slot);
276         } else {
277             retval = &PL_sv_undef;
278         }
279         SHAREDSvUNLOCK(shared);
280         RETVAL = retval;
281         OUTPUT:
282         RETVAL
283
284
285 SV*
286 SHIFT(self)
287         SV* self
288         CODE:
289         shared_sv* shared = (shared_sv*) SvIV(SvRV(self));
290         shared_sv* slot;
291         SV* retval;
292         SHAREDSvLOCK(shared);
293         SHAREDSvEDIT(shared);
294         retval = av_shift((AV*)SHAREDSvGET(shared));
295         SHAREDSvRELEASE(shared);
296         if(retval && SvIV(retval)) {
297             slot = (shared_sv*) SvIV(retval);
298             retval = newSVsv(SHAREDSvGET(slot));
299             Perl_sharedsv_thrcnt_dec(aTHX_ slot);
300         } else {
301             retval = &PL_sv_undef;
302         }
303         SHAREDSvUNLOCK(shared);
304         RETVAL = retval;
305         OUTPUT:
306         RETVAL
307
308 void
309 CLEAR(self)
310         SV* self
311         CODE:
312         shared_sv* shared = (shared_sv*) SvIV(SvRV(self));
313         shared_sv* slot;
314         SV** svp;
315         I32 i;
316         SHAREDSvLOCK(shared);
317         svp = AvARRAY((AV*)SHAREDSvGET(shared));
318         i   = AvFILLp((AV*)SHAREDSvGET(shared));
319         while ( i >= 0) {
320             if(SvIV(svp[i])) {
321                 Perl_sharedsv_thrcnt_dec(aTHX_ (shared_sv*) SvIV(svp[i]));
322             }
323             i--;
324         }
325         SHAREDSvEDIT(shared);
326         av_clear((AV*)SHAREDSvGET(shared));
327         SHAREDSvRELEASE(shared);
328         SHAREDSvUNLOCK(shared);
329         
330 void
331 EXTEND(self, count)
332         SV* self
333         SV* count
334         CODE:
335         shared_sv* shared = (shared_sv*) SvIV(SvRV(self));
336         SHAREDSvEDIT(shared);
337         av_extend((AV*)SHAREDSvGET(shared), (I32) SvIV(count));
338         SHAREDSvRELEASE(shared);
339
340
341
342
343 SV*
344 EXISTS(self, index)
345         SV* self
346         SV* index
347         CODE:
348         shared_sv* shared = (shared_sv*) SvIV(SvRV(self));
349         I32 exists;
350         SHAREDSvLOCK(shared);
351         exists = av_exists((AV*) SHAREDSvGET(shared), (I32) SvIV(index));
352         if(exists) {
353             RETVAL = &PL_sv_yes;
354         } else {
355             RETVAL = &PL_sv_no;
356         }
357         SHAREDSvUNLOCK(shared);
358
359 void
360 STORESIZE(self,count)
361         SV* self
362         SV* count
363         CODE:
364         shared_sv* shared = (shared_sv*) SvIV(SvRV(self));
365         SHAREDSvEDIT(shared);
366         av_fill((AV*) SHAREDSvGET(shared), (I32) SvIV(count));
367         SHAREDSvRELEASE(shared);
368
369 SV*
370 FETCHSIZE(self)
371         SV* self
372         CODE:
373         shared_sv* shared = (shared_sv*) SvIV(SvRV(self));
374         SHAREDSvLOCK(shared);
375         RETVAL = newSViv(av_len((AV*) SHAREDSvGET(shared)) + 1);
376         SHAREDSvUNLOCK(shared);
377         OUTPUT:
378         RETVAL
379
380 SV*
381 DELETE(self,index)
382         SV* self
383         SV* index
384         CODE:
385         shared_sv* shared = (shared_sv*) SvIV(SvRV(self));
386         shared_sv* slot;
387         SHAREDSvLOCK(shared);
388         if(av_exists((AV*) SHAREDSvGET(shared), (I32) SvIV(index))) {
389             SV* tmp;
390             SHAREDSvEDIT(shared);
391             tmp = av_delete((AV*)SHAREDSvGET(shared), (I32) SvIV(index),0);
392             SHAREDSvRELEASE(shared);
393             if(SvIV(tmp)) {
394                 slot = (shared_sv*) SvIV(tmp);
395                 RETVAL = newSVsv(SHAREDSvGET(slot));
396                 Perl_sharedsv_thrcnt_dec(aTHX_ slot);               
397             } else {
398                 RETVAL = &PL_sv_undef;
399             }       
400         } else {
401             RETVAL = &PL_sv_undef;
402         }       
403         SHAREDSvUNLOCK(shared);
404         OUTPUT:
405         RETVAL
406
407 AV*
408 SPLICE(self, offset, length, ...)
409         SV* self
410         SV* offset
411         SV* length
412         CODE:
413         croak("Splice is not implmented for shared arrays");
414         
415