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

# 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.3 static HV *guard_stash;
8    
9 root 1.1 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 root 1.2 PUSHSTACKi (PERLSI_DESTROY);
29 root 1.1
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 root 1.3 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 root 1.1 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 root 1.3 SvOBJECT_on (guard);
98     ++PL_sv_objcount;
99     SvSTASH_set (guard, (HV*)SvREFCNT_inc ((SV *)guard_stash));
100 root 1.1 }
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     }