ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Guard/Guard.xs
Revision: 1.1
Committed: Sat Dec 13 17:37:22 2008 UTC (15 years, 5 months ago) by root
Branch: MAIN
Log Message:
initial check-in

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