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