| 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
|
|
|
|
|
|
|
} |