ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Guard/Guard.xs
Revision: 1.10
Committed: Sun Jul 19 04:43:47 2009 UTC (14 years, 10 months ago) by root
Branch: MAIN
Changes since 1.9: +8 -0 lines
Log Message:
*** empty log message ***

File Contents

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