line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
3886
|
|
|
|
|
|
static SV *wrap_thing(U16 mgcode, void *ptr, HV *stash, SV *temple) { |
2
|
|
|
|
|
|
|
SV *ref; |
3
|
|
|
|
|
|
|
MAGIC **mgp; |
4
|
|
|
|
|
|
|
MAGIC *mg; |
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
assert(ptr); |
7
|
|
|
|
|
|
|
assert(stash); |
8
|
|
|
|
|
|
|
|
9
|
3886
|
50
|
|
|
|
|
if (!temple) |
10
|
0
|
|
|
|
|
|
temple = (SV*)newHV(); |
11
|
|
|
|
|
|
|
else |
12
|
3886
|
|
|
|
|
|
SvREFCNT_inc(temple); |
13
|
3886
|
100
|
|
|
|
|
if (SvOBJECT(temple)) |
14
|
1
|
|
|
|
|
|
croak("Can't attach to blessed reference"); |
15
|
|
|
|
|
|
|
assert(!SvROK(temple)); |
16
|
|
|
|
|
|
|
assert(mg_find(temple, '~') == 0); /* multiplicity disallowed! */ |
17
|
|
|
|
|
|
|
|
18
|
3885
|
|
|
|
|
|
ref = newRV_noinc(temple); |
19
|
3885
|
|
|
|
|
|
sv_bless(ref, stash); |
20
|
|
|
|
|
|
|
|
21
|
3885
|
|
|
|
|
|
mgp = &SvMAGIC(temple); |
22
|
3885
|
50
|
|
|
|
|
while ((mg = *mgp)) |
23
|
0
|
|
|
|
|
|
mgp = &mg->mg_moremagic; |
24
|
|
|
|
|
|
|
|
25
|
3885
|
|
|
|
|
|
New(0, mg, 1, MAGIC); |
26
|
3885
|
|
|
|
|
|
Zero(mg, 1, MAGIC); |
27
|
3885
|
|
|
|
|
|
mg->mg_type = '~'; |
28
|
3885
|
|
|
|
|
|
mg->mg_ptr = (char*) ptr; /* NOT refcnt'd */ |
29
|
3885
|
|
|
|
|
|
mg->mg_private = mgcode; |
30
|
3885
|
|
|
|
|
|
*mgp = mg; |
31
|
|
|
|
|
|
|
|
32
|
3885
|
|
|
|
|
|
return ref; |
33
|
|
|
|
|
|
|
} |
34
|
|
|
|
|
|
|
|
35
|
145011
|
|
|
|
|
|
static void* sv_2thing(U16 mgcode, SV *sv) { |
36
|
|
|
|
|
|
|
MAGIC *mg; |
37
|
145011
|
|
|
|
|
|
SV *origsv = sv; |
38
|
145011
|
50
|
|
|
|
|
if (!sv || !SvROK(sv)) |
|
|
100
|
|
|
|
|
|
39
|
1
|
|
|
|
|
|
croak("sv_2thing: not a reference?"); |
40
|
145010
|
|
|
|
|
|
sv = SvRV(sv); |
41
|
145010
|
100
|
|
|
|
|
if (SvTYPE(sv) < SVt_PVMG) |
42
|
3
|
|
|
|
|
|
croak("sv_2thing: not a thing"); |
43
|
145007
|
50
|
|
|
|
|
if (!SvOBJECT(sv)) |
44
|
0
|
|
|
|
|
|
croak("sv_2thing: not an object"); |
45
|
145007
|
|
|
|
|
|
mg = mg_find(sv, '~'); |
46
|
145007
|
50
|
|
|
|
|
if (mg) { |
47
|
145007
|
100
|
|
|
|
|
if (mg->mg_private != mgcode) { |
48
|
1
|
|
|
|
|
|
croak("Can't find event magic (SV=0x%x)", sv); |
49
|
|
|
|
|
|
|
} |
50
|
145006
|
|
|
|
|
|
return (void*) mg->mg_ptr; |
51
|
|
|
|
|
|
|
} |
52
|
0
|
|
|
|
|
|
croak("sv_2thing: can't decode SV=0x%x", origsv); |
53
|
0
|
|
|
|
|
|
return 0; |
54
|
|
|
|
|
|
|
} |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
#define MG_WATCHER_CODE ((((unsigned)'e')<<8) + (unsigned)'v') |
57
|
|
|
|
|
|
|
|
58
|
3885
|
|
|
|
|
|
static SV *wrap_watcher(void *ptr, HV *stash, SV *temple) { |
59
|
3885
|
|
|
|
|
|
return wrap_thing(MG_WATCHER_CODE, ptr, stash, temple); |
60
|
|
|
|
|
|
|
} |
61
|
|
|
|
|
|
|
|
62
|
117883
|
|
|
|
|
|
SV *watcher_2sv(pe_watcher *wa) { /**SLOW IS OKAY**/ |
63
|
|
|
|
|
|
|
assert(!WaDESTROYED(wa)); |
64
|
117883
|
50
|
|
|
|
|
if (!wa->mysv) { |
65
|
0
|
|
|
|
|
|
wa->mysv = wrap_watcher(wa, wa->vtbl->stash, 0); |
66
|
|
|
|
|
|
|
if (WaDEBUGx(wa) >= 4) { |
67
|
|
|
|
|
|
|
STRLEN n_a; |
68
|
|
|
|
|
|
|
warn("Watcher=0x%x '%s' wrapped with SV=0x%x", |
69
|
|
|
|
|
|
|
wa, SvPV(wa->desc, n_a), SvRV(wa->mysv)); |
70
|
|
|
|
|
|
|
} |
71
|
|
|
|
|
|
|
} |
72
|
117883
|
|
|
|
|
|
return SvREFCNT_inc(sv_2mortal(wa->mysv)); |
73
|
|
|
|
|
|
|
} |
74
|
|
|
|
|
|
|
|
75
|
145001
|
|
|
|
|
|
void* sv_2watcher(SV *sv) { |
76
|
145001
|
|
|
|
|
|
return sv_2thing(MG_WATCHER_CODE, sv); |
77
|
|
|
|
|
|
|
} |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
#define MG_GENERICSRC_CODE 2422 /* randomly chosen */ |
80
|
|
|
|
|
|
|
|
81
|
1
|
|
|
|
|
|
static SV *wrap_genericsrc(void *ptr, HV *stash, SV *temple) { |
82
|
1
|
|
|
|
|
|
return wrap_thing(MG_GENERICSRC_CODE, ptr, stash, temple); |
83
|
|
|
|
|
|
|
} |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
static HV *pe_genericsrc_stash; |
86
|
|
|
|
|
|
|
|
87
|
1
|
|
|
|
|
|
static SV *genericsrc_2sv(pe_genericsrc *src) { /**SLOW IS OKAY**/ |
88
|
1
|
50
|
|
|
|
|
if (!src->mysv) { |
89
|
0
|
|
|
|
|
|
src->mysv = wrap_genericsrc(src, pe_genericsrc_stash, 0); |
90
|
|
|
|
|
|
|
} |
91
|
1
|
|
|
|
|
|
return SvREFCNT_inc(sv_2mortal(src->mysv)); |
92
|
|
|
|
|
|
|
} |
93
|
|
|
|
|
|
|
|
94
|
10
|
|
|
|
|
|
static void* sv_2genericsrc(SV *sv) { |
95
|
10
|
|
|
|
|
|
return sv_2thing(MG_GENERICSRC_CODE, sv); |
96
|
|
|
|
|
|
|
} |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
/* |
99
|
|
|
|
|
|
|
Events have a short lifetime. mysv is kept alive until the event |
100
|
|
|
|
|
|
|
has been serviced. Once perl finally releases mysv then the event |
101
|
|
|
|
|
|
|
is deallocated (or, more likely, recycled). |
102
|
|
|
|
|
|
|
*/ |
103
|
|
|
|
|
|
|
|
104
|
110980
|
|
|
|
|
|
SV *event_2sv(pe_event *ev) { /**MAKE FAST**/ |
105
|
110980
|
100
|
|
|
|
|
if (!ev->mysv) { |
106
|
110969
|
|
|
|
|
|
SV *rv = newSV(0); |
107
|
110969
|
|
|
|
|
|
SV *sv = newSVrv(rv,0); |
108
|
110969
|
|
|
|
|
|
sv_bless(rv, ev->vtbl->stash); |
109
|
110969
|
|
|
|
|
|
sv_setiv(sv, PTR2IV(ev)); |
110
|
110969
|
|
|
|
|
|
ev->mysv = rv; |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
if (WaDEBUGx(ev->up) >= 4) { |
113
|
|
|
|
|
|
|
STRLEN n_a; |
114
|
|
|
|
|
|
|
warn("Event=0x%x '%s' wrapped with SV=0x%x", |
115
|
|
|
|
|
|
|
ev, SvPV(ev->up->desc, n_a), SvRV(ev->mysv)); |
116
|
|
|
|
|
|
|
} |
117
|
|
|
|
|
|
|
} |
118
|
110980
|
|
|
|
|
|
return SvREFCNT_inc(sv_2mortal(ev->mysv)); |
119
|
|
|
|
|
|
|
} |
120
|
|
|
|
|
|
|
|
121
|
331823
|
|
|
|
|
|
void *sv_2event(SV *sv) { |
122
|
|
|
|
|
|
|
void *ptr; |
123
|
|
|
|
|
|
|
assert(sv); |
124
|
|
|
|
|
|
|
assert(SvROK(sv)); |
125
|
331823
|
|
|
|
|
|
sv = SvRV(sv); |
126
|
331823
|
50
|
|
|
|
|
ptr = INT2PTR(void *, SvIV(sv)); |
127
|
|
|
|
|
|
|
assert(ptr); |
128
|
331823
|
|
|
|
|
|
return ptr; |
129
|
|
|
|
|
|
|
} |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
/***************************************************************/ |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
#define VERIFYINTERVAL(name, f) \ |
134
|
|
|
|
|
|
|
STMT_START { NV ign; sv_2interval(name, f, &ign); } STMT_END |
135
|
|
|
|
|
|
|
|
136
|
140
|
|
|
|
|
|
int sv_2interval(char *label, SV *in, NV *out) { |
137
|
140
|
|
|
|
|
|
SV *sv = in; |
138
|
140
|
50
|
|
|
|
|
if (!sv) return 0; |
139
|
140
|
50
|
|
|
|
|
if (SvGMAGICAL(sv)) |
140
|
0
|
|
|
|
|
|
mg_get(sv); |
141
|
140
|
100
|
|
|
|
|
if (!SvOK(sv)) return 0; |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
142
|
124
|
50
|
|
|
|
|
if (SvROK(sv)) |
143
|
0
|
|
|
|
|
|
sv = SvRV(sv); |
144
|
124
|
50
|
|
|
|
|
if (!SvOK(sv)) { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
145
|
0
|
|
|
|
|
|
warn("Event: %s interval undef", label); |
146
|
0
|
|
|
|
|
|
*out = 0; |
147
|
124
|
100
|
|
|
|
|
} else if (SvNOK(sv)) { |
148
|
122
|
|
|
|
|
|
*out = SvNVX(sv); |
149
|
2
|
50
|
|
|
|
|
} else if (SvIOK(sv)) { |
150
|
2
|
|
|
|
|
|
*out = SvIVX(sv); |
151
|
0
|
0
|
|
|
|
|
} else if (looks_like_number(sv)) { |
152
|
0
|
0
|
|
|
|
|
*out = SvNV(sv); |
153
|
|
|
|
|
|
|
} else { |
154
|
0
|
|
|
|
|
|
sv_dump(in); |
155
|
0
|
|
|
|
|
|
croak("Event: %s interval must be a number or reference to a number", |
156
|
|
|
|
|
|
|
label); |
157
|
0
|
|
|
|
|
|
return 0; |
158
|
|
|
|
|
|
|
} |
159
|
124
|
50
|
|
|
|
|
if (*out < 0) { |
160
|
0
|
|
|
|
|
|
warn("Event: %s has negative timeout %.2f (clipped to zero)", |
161
|
|
|
|
|
|
|
label, *out); |
162
|
0
|
|
|
|
|
|
*out = 0; |
163
|
|
|
|
|
|
|
} |
164
|
124
|
|
|
|
|
|
return 1; |
165
|
|
|
|
|
|
|
} |
166
|
|
|
|
|
|
|
|
167
|
110101
|
|
|
|
|
|
SV* events_mask_2sv(int mask) { |
168
|
110101
|
|
|
|
|
|
SV *ret = newSV(0); |
169
|
110101
|
50
|
|
|
|
|
(void)SvUPGRADE(ret, SVt_PVIV); |
170
|
110101
|
|
|
|
|
|
sv_setpvn(ret, "", 0); |
171
|
110101
|
100
|
|
|
|
|
if (mask & PE_R) sv_catpv(ret, "r"); |
172
|
110101
|
100
|
|
|
|
|
if (mask & PE_W) sv_catpv(ret, "w"); |
173
|
110101
|
50
|
|
|
|
|
if (mask & PE_E) sv_catpv(ret, "e"); |
174
|
110101
|
100
|
|
|
|
|
if (mask & PE_T) sv_catpv(ret, "t"); |
175
|
110101
|
|
|
|
|
|
SvIVX(ret) = mask; |
176
|
110101
|
|
|
|
|
|
SvIOK_on(ret); |
177
|
110101
|
|
|
|
|
|
return ret; |
178
|
|
|
|
|
|
|
} |
179
|
|
|
|
|
|
|
|
180
|
8
|
|
|
|
|
|
int sv_2events_mask(SV *sv, int bits) { |
181
|
8
|
100
|
|
|
|
|
if (SvPOK(sv)) { |
182
|
6
|
|
|
|
|
|
UV got=0; |
183
|
|
|
|
|
|
|
int xx; |
184
|
|
|
|
|
|
|
STRLEN el; |
185
|
6
|
50
|
|
|
|
|
char *ep = SvPV(sv,el); |
186
|
12
|
100
|
|
|
|
|
for (xx=0; xx < el; xx++) { |
187
|
6
|
|
|
|
|
|
switch (ep[xx]) { |
188
|
4
|
50
|
|
|
|
|
case 'r': if (bits & PE_R) { got |= PE_R; continue; } |
189
|
2
|
50
|
|
|
|
|
case 'w': if (bits & PE_W) { got |= PE_W; continue; } |
190
|
0
|
0
|
|
|
|
|
case 'e': if (bits & PE_E) { got |= PE_E; continue; } |
191
|
0
|
0
|
|
|
|
|
case 't': if (bits & PE_T) { got |= PE_T; continue; } |
192
|
|
|
|
|
|
|
} |
193
|
0
|
|
|
|
|
|
warn("Ignored '%c' in poll mask", ep[xx]); |
194
|
|
|
|
|
|
|
} |
195
|
6
|
|
|
|
|
|
return got; |
196
|
|
|
|
|
|
|
} |
197
|
2
|
50
|
|
|
|
|
else if (SvIOK(sv)) { |
198
|
2
|
|
|
|
|
|
UV extra = SvIVX(sv) & ~bits; |
199
|
2
|
50
|
|
|
|
|
if (extra) warn("Ignored extra bits (0x%x) in poll mask", extra); |
200
|
2
|
|
|
|
|
|
return SvIVX(sv) & bits; |
201
|
|
|
|
|
|
|
} |
202
|
|
|
|
|
|
|
else { |
203
|
0
|
|
|
|
|
|
sv_dump(sv); |
204
|
0
|
|
|
|
|
|
croak("Must be a string /[rwet]/ or bit mask"); |
205
|
0
|
|
|
|
|
|
return 0; /* NOTREACHED */ |
206
|
|
|
|
|
|
|
} |
207
|
|
|
|
|
|
|
} |