ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Guard/Guard.xs
Revision: 1.3
Committed: Sat Dec 13 19:14:58 2008 UTC (15 years, 5 months ago) by root
Branch: MAIN
Changes since 1.2: +14 -0 lines
Log Message:
*** empty log message ***

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