ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Guard/Guard.xs
Revision: 1.5
Committed: Sat Dec 13 21:47:07 2008 UTC (15 years, 5 months ago) by root
Branch: MAIN
CVS Tags: rel-0_5
Changes since 1.4: +0 -1 lines
Log Message:
0.5

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 HV *guard_stash;
8
9 static SV *
10 guard_get_cv (pTHX_ SV *cb_sv)
11 {
12 HV *st;
13 GV *gvp;
14 CV *cv = sv_2cv (cb_sv, &st, &gvp, 0);
15
16 if (!cv)
17 croak ("expected a CODE reference for guard");
18
19 return (SV *)cv;
20 }
21
22 static void
23 exec_guard_cb (pTHX_ SV *cb)
24 {
25 dSP;
26 SV *saveerr = SvOK (ERRSV) ? sv_mortalcopy (ERRSV) : 0;
27 SV *savedie = PL_diehook;
28
29 PL_diehook = 0;
30
31 PUSHSTACKi (PERLSI_DESTROY);
32
33 PUSHMARK (SP);
34 PUTBACK;
35 call_sv (cb, G_VOID | G_DISCARD | G_EVAL);
36 SPAGAIN;
37
38 if (SvTRUE (ERRSV))
39 {
40 PUSHMARK (SP);
41 PUTBACK;
42 call_sv (get_sv ("Guard::DIED", 1), G_VOID | G_DISCARD | G_EVAL | G_KEEPERR);
43 SPAGAIN;
44
45 sv_setpvn (ERRSV, "", 0);
46 }
47
48 if (saveerr)
49 sv_setsv (ERRSV, saveerr);
50
51 {
52 SV *oldhook = PL_diehook;
53 PL_diehook = savedie;
54 SvREFCNT_dec (oldhook);
55 }
56
57 POPSTACK;
58 }
59
60 static void
61 scope_guard_cb (pTHX_ void *cv)
62 {
63 exec_guard_cb (aTHX_ sv_2mortal ((SV *)cv));
64 }
65
66 static int
67 guard_free (pTHX_ SV *cv, MAGIC *mg)
68 {
69 exec_guard_cb (aTHX_ mg->mg_obj);
70 }
71
72 static MGVTBL guard_vtbl = {
73 0, 0, 0, 0,
74 guard_free
75 };
76
77 MODULE = Guard PACKAGE = Guard
78
79 BOOT:
80 guard_stash = gv_stashpv ("Guard", 1);
81
82 void
83 CLONE (...)
84 PROTOTYPE: @
85 CODE:
86 guard_stash = gv_stashpv ("Guard", 1);
87
88 void
89 scope_guard (SV *block)
90 PROTOTYPE: &
91 CODE:
92 LEAVE; /* unfortunately, perl sandwiches XS calls into ENTER/LEAVE */
93 SAVEDESTRUCTOR_X (scope_guard_cb, (void *)SvREFCNT_inc (guard_get_cv (aTHX_ block)));
94 ENTER; /* unfortunately, perl sandwiches XS calls into ENTER/LEAVE */
95
96 SV *
97 guard (SV *block)
98 PROTOTYPE: &
99 CODE:
100 {
101 SV *cv = guard_get_cv (aTHX_ block);
102 SV *guard = NEWSV (0, 0);
103 SvUPGRADE (guard, SVt_PVMG);
104 sv_magicext (guard, cv, PERL_MAGIC_ext, &guard_vtbl, 0, 0);
105 RETVAL = newRV_noinc (guard);
106 SvOBJECT_on (guard);
107 ++PL_sv_objcount;
108 SvSTASH_set (guard, (HV*)SvREFCNT_inc ((SV *)guard_stash));
109 }
110 OUTPUT:
111 RETVAL
112
113 void
114 cancel (SV *guard)
115 PROTOTYPE: $
116 CODE:
117 {
118 MAGIC *mg;
119 if (!SvROK (guard)
120 || !(mg = mg_find (SvRV (guard), PERL_MAGIC_ext))
121 || mg->mg_virtual != &guard_vtbl)
122 croak ("Guard::cancel called on a non-guard object");
123
124 SvREFCNT_dec (mg->mg_obj);
125 mg->mg_obj = 0;
126 mg->mg_virtual = 0;
127 }