ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Guard/Guard.xs
Revision: 1.2
Committed: Sat Dec 13 17:49:12 2008 UTC (15 years, 5 months ago) by root
Branch: MAIN
CVS Tags: rel-0_1
Changes since 1.1: +1 -1 lines
Log Message:
fixes

File Contents

# Content
1 #define PERL_NO_GET_CONTEXT
2
3 #include "EXTERN.h"
4 #include "perl.h"
5 #include "XSUB.h"
6
7 static SV *
8 guard_get_cv (pTHX_ SV *cb_sv)
9 {
10 HV *st;
11 GV *gvp;
12 CV *cv = sv_2cv (cb_sv, &st, &gvp, 0);
13
14 if (!cv)
15 croak ("expected a CODE reference for guard");
16
17 return (SV *)cv;
18 }
19
20 static void
21 exec_guard_cb (pTHX_ SV *cb)
22 {
23 dSP;
24 SV *saveerr = SvOK (ERRSV) ? sv_mortalcopy (ERRSV) : 0;
25
26 PUSHSTACKi (PERLSI_DESTROY);
27
28 PUSHMARK (SP);
29 PUTBACK;
30 call_sv (cb, G_VOID | G_DISCARD | G_EVAL);
31 SPAGAIN;
32
33 if (SvTRUE (ERRSV))
34 {
35 PUSHMARK (SP);
36 PUTBACK;
37 call_sv (get_sv ("Guard::DIED", 1), G_VOID | G_DISCARD | G_EVAL | G_KEEPERR);
38 SPAGAIN;
39
40 sv_setsv (ERRSV, &PL_sv_undef);
41 }
42
43 if (saveerr)
44 sv_setsv (ERRSV, saveerr);
45
46 POPSTACK;
47 }
48
49 static void
50 scope_guard_cb (pTHX_ void *cv)
51 {
52 exec_guard_cb (aTHX_ sv_2mortal ((SV *)cv));
53 }
54
55 static int
56 guard_free (pTHX_ SV *cv, MAGIC *mg)
57 {
58 exec_guard_cb (aTHX_ mg->mg_obj);
59 }
60
61 static MGVTBL guard_vtbl = {
62 0, 0, 0, 0,
63 guard_free
64 };
65
66 MODULE = Guard PACKAGE = Guard
67
68 void
69 scope_guard (SV *block)
70 PROTOTYPE: &
71 CODE:
72 LEAVE; /* unfortunately, perl sandwiches XS calls into ENTER/LEAVE */
73 SAVEDESTRUCTOR_X (scope_guard_cb, (void *)SvREFCNT_inc (guard_get_cv (aTHX_ block)));
74 ENTER; /* unfortunately, perl sandwiches XS calls into ENTER/LEAVE */
75
76 SV *
77 guard (SV *block)
78 PROTOTYPE: &
79 CODE:
80 {
81 SV *cv = guard_get_cv (aTHX_ block);
82 SV *guard = NEWSV (0, 0);
83 SvUPGRADE (guard, SVt_PVMG);
84 sv_magicext (guard, cv, PERL_MAGIC_ext, &guard_vtbl, 0, 0);
85 RETVAL = newRV_noinc (guard);
86 }
87 OUTPUT:
88 RETVAL
89
90 void
91 cancel (SV *guard)
92 PROTOTYPE: $
93 CODE:
94 {
95 MAGIC *mg;
96 if (!SvROK (guard)
97 || !(mg = mg_find (SvRV (guard), PERL_MAGIC_ext))
98 || mg->mg_virtual != &guard_vtbl)
99 croak ("Guard::cancel called on a non-guard object");
100
101 SvREFCNT_dec (mg->mg_obj);
102 mg->mg_obj = 0;
103 mg->mg_virtual = 0;
104 }