line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package POE::Wheel::ReadWrite; |
2
|
|
|
|
|
|
|
|
3
|
26
|
|
|
26
|
|
7203
|
use strict; |
|
26
|
|
|
|
|
34
|
|
|
26
|
|
|
|
|
922
|
|
4
|
|
|
|
|
|
|
|
5
|
26
|
|
|
26
|
|
104
|
use vars qw($VERSION @ISA); |
|
26
|
|
|
|
|
28
|
|
|
26
|
|
|
|
|
1461
|
|
6
|
|
|
|
|
|
|
$VERSION = '1.366'; # NOTE - Should be #.### (three decimal places) |
7
|
|
|
|
|
|
|
|
8
|
26
|
|
|
26
|
|
112
|
use Carp qw( croak carp ); |
|
26
|
|
|
|
|
37
|
|
|
26
|
|
|
|
|
1279
|
|
9
|
26
|
|
|
26
|
|
120
|
use POE qw(Wheel Driver::SysRW Filter::Line); |
|
26
|
|
|
|
|
28
|
|
|
26
|
|
|
|
|
215
|
|
10
|
|
|
|
|
|
|
push @ISA, qw(POE::Wheel); |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
# Offsets into $self. |
13
|
|
|
|
|
|
|
sub HANDLE_INPUT () { 0 } |
14
|
|
|
|
|
|
|
sub HANDLE_OUTPUT () { 1 } |
15
|
|
|
|
|
|
|
sub FILTER_INPUT () { 2 } |
16
|
|
|
|
|
|
|
sub FILTER_OUTPUT () { 3 } |
17
|
|
|
|
|
|
|
sub DRIVER_BOTH () { 4 } |
18
|
|
|
|
|
|
|
sub EVENT_INPUT () { 5 } |
19
|
|
|
|
|
|
|
sub EVENT_ERROR () { 6 } |
20
|
|
|
|
|
|
|
sub EVENT_FLUSHED () { 7 } |
21
|
|
|
|
|
|
|
sub WATERMARK_WRITE_MARK_HIGH () { 8 } |
22
|
|
|
|
|
|
|
sub WATERMARK_WRITE_MARK_LOW () { 9 } |
23
|
|
|
|
|
|
|
sub WATERMARK_WRITE_EVENT_HIGH () { 10 } |
24
|
|
|
|
|
|
|
sub WATERMARK_WRITE_EVENT_LOW () { 11 } |
25
|
|
|
|
|
|
|
sub WATERMARK_WRITE_STATE () { 12 } |
26
|
|
|
|
|
|
|
sub DRIVER_BUFFERED_OUT_OCTETS () { 13 } |
27
|
|
|
|
|
|
|
sub STATE_WRITE () { 14 } |
28
|
|
|
|
|
|
|
sub STATE_READ () { 15 } |
29
|
|
|
|
|
|
|
sub UNIQUE_ID () { 16 } |
30
|
|
|
|
|
|
|
sub AUTOFLUSH () { 17 } |
31
|
|
|
|
|
|
|
|
32
|
0
|
|
|
0
|
0
|
0
|
sub CRIMSON_SCOPE_HACK ($) { 0 } |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
sub new { |
37
|
158
|
|
|
158
|
1
|
8405
|
my $type = shift; |
38
|
158
|
|
|
|
|
644
|
my %params = @_; |
39
|
|
|
|
|
|
|
|
40
|
158
|
100
|
100
|
|
|
930
|
croak "wheels no longer require a kernel reference as their first parameter" |
41
|
|
|
|
|
|
|
if (@_ && (ref($_[0]) eq 'POE::Kernel')); |
42
|
|
|
|
|
|
|
|
43
|
156
|
50
|
|
|
|
304
|
croak "$type requires a working Kernel" unless defined $poe_kernel; |
44
|
|
|
|
|
|
|
|
45
|
156
|
|
|
|
|
157
|
my ($in_handle, $out_handle); |
46
|
156
|
100
|
|
|
|
320
|
if (defined $params{Handle}) { |
47
|
148
|
50
|
|
|
|
298
|
carp "Ignoring InputHandle parameter (Handle parameter takes precedence)" |
48
|
|
|
|
|
|
|
if defined $params{InputHandle}; |
49
|
148
|
50
|
|
|
|
257
|
carp "Ignoring OutputHandle parameter (Handle parameter takes precedence)" |
50
|
|
|
|
|
|
|
if defined $params{OutputHandle}; |
51
|
148
|
|
|
|
|
278
|
$in_handle = $out_handle = delete $params{Handle}; |
52
|
|
|
|
|
|
|
} |
53
|
|
|
|
|
|
|
else { |
54
|
8
|
100
|
|
|
|
215
|
croak "Handle or InputHandle required" |
55
|
|
|
|
|
|
|
unless defined $params{InputHandle}; |
56
|
6
|
100
|
|
|
|
220
|
croak "Handle or OutputHandle required" |
57
|
|
|
|
|
|
|
unless defined $params{OutputHandle}; |
58
|
4
|
|
|
|
|
8
|
$in_handle = delete $params{InputHandle}; |
59
|
4
|
|
|
|
|
5
|
$out_handle = delete $params{OutputHandle}; |
60
|
|
|
|
|
|
|
} |
61
|
|
|
|
|
|
|
|
62
|
152
|
|
|
|
|
156
|
my ($in_filter, $out_filter); |
63
|
152
|
100
|
|
|
|
278
|
if (defined $params{Filter}) { |
64
|
109
|
50
|
|
|
|
231
|
carp "Ignoring InputFilter parameter (Filter parameter takes precedence)" |
65
|
|
|
|
|
|
|
if (defined $params{InputFilter}); |
66
|
109
|
50
|
|
|
|
452
|
carp "Ignoring OutputFilter parameter (Filter parameter takes precedence)" |
67
|
|
|
|
|
|
|
if (defined $params{OutputFilter}); |
68
|
109
|
|
|
|
|
176
|
$in_filter = $out_filter = delete $params{Filter}; |
69
|
|
|
|
|
|
|
} |
70
|
|
|
|
|
|
|
else { |
71
|
43
|
|
|
|
|
50
|
$in_filter = delete $params{InputFilter}; |
72
|
43
|
|
|
|
|
43
|
$out_filter = delete $params{OutputFilter}; |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
# If neither Filter, InputFilter or OutputFilter is defined, then |
75
|
|
|
|
|
|
|
# they default to POE::Filter::Line. |
76
|
43
|
50
|
33
|
|
|
127
|
unless (defined $in_filter and defined $out_filter) { |
77
|
43
|
|
|
|
|
164
|
my $new_filter = POE::Filter::Line->new(); |
78
|
43
|
50
|
|
|
|
87
|
$in_filter = $new_filter unless defined $in_filter; |
79
|
43
|
50
|
|
|
|
100
|
$out_filter = $new_filter unless defined $out_filter; |
80
|
|
|
|
|
|
|
} |
81
|
|
|
|
|
|
|
} |
82
|
|
|
|
|
|
|
|
83
|
152
|
|
|
|
|
236
|
my $driver = delete $params{Driver}; |
84
|
152
|
100
|
|
|
|
1101
|
$driver = POE::Driver::SysRW->new() unless defined $driver; |
85
|
|
|
|
|
|
|
|
86
|
152
|
|
|
|
|
149
|
{ my $mark_errors = 0; |
|
152
|
|
|
|
|
160
|
|
87
|
152
|
100
|
100
|
|
|
837
|
if (defined($params{HighMark}) xor defined($params{LowMark})) { |
|
|
100
|
|
|
|
|
|
88
|
4
|
|
|
|
|
424
|
carp "HighMark and LowMark parameters require each-other"; |
89
|
4
|
|
|
|
|
175
|
$mark_errors++; |
90
|
|
|
|
|
|
|
} |
91
|
|
|
|
|
|
|
# Then they both exist, and they must be checked. |
92
|
|
|
|
|
|
|
elsif (defined $params{HighMark}) { |
93
|
12
|
50
|
33
|
|
|
51
|
unless (defined($params{HighMark}) and defined($params{LowMark})) { |
94
|
0
|
|
|
|
|
0
|
carp "HighMark and LowMark parameters must both be defined"; |
95
|
0
|
|
|
|
|
0
|
$mark_errors++; |
96
|
|
|
|
|
|
|
} |
97
|
12
|
100
|
100
|
|
|
44
|
unless (($params{HighMark} > 0) and ($params{LowMark} > 0)) { |
98
|
6
|
|
|
|
|
625
|
carp "HighMark and LowMark parameters must be above 0"; |
99
|
6
|
|
|
|
|
255
|
$mark_errors++; |
100
|
|
|
|
|
|
|
} |
101
|
|
|
|
|
|
|
} |
102
|
152
|
100
|
100
|
|
|
443
|
if (defined $params{HighEvent} and not defined $params{HighMark}) { |
103
|
6
|
|
|
|
|
577
|
carp "HighEvent requires a corresponding HighMark"; |
104
|
6
|
|
|
|
|
210
|
$mark_errors++; |
105
|
|
|
|
|
|
|
} |
106
|
152
|
100
|
100
|
|
|
650
|
if (defined($params{LowMark}) xor defined($params{LowEvent})) { |
107
|
8
|
|
|
|
|
744
|
carp "LowMark and LowEvent parameters require each-other"; |
108
|
8
|
|
|
|
|
290
|
$mark_errors++; |
109
|
|
|
|
|
|
|
} |
110
|
152
|
100
|
|
|
|
1860
|
croak "Water mark errors" if $mark_errors; |
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
|
113
|
134
|
|
|
|
|
630
|
my $self = bless [ |
114
|
|
|
|
|
|
|
$in_handle, # HANDLE_INPUT |
115
|
|
|
|
|
|
|
$out_handle, # HANDLE_OUTPUT |
116
|
|
|
|
|
|
|
$in_filter, # FILTER_INPUT |
117
|
|
|
|
|
|
|
$out_filter, # FILTER_OUTPUT |
118
|
|
|
|
|
|
|
$driver, # DRIVER_BOTH |
119
|
|
|
|
|
|
|
delete $params{InputEvent}, # EVENT_INPUT |
120
|
|
|
|
|
|
|
delete $params{ErrorEvent}, # EVENT_ERROR |
121
|
|
|
|
|
|
|
delete $params{FlushedEvent}, # EVENT_FLUSHED |
122
|
|
|
|
|
|
|
# Water marks. |
123
|
|
|
|
|
|
|
delete $params{HighMark}, # WATERMARK_WRITE_MARK_HIGH |
124
|
|
|
|
|
|
|
delete $params{LowMark}, # WATERMARK_WRITE_MARK_LOW |
125
|
|
|
|
|
|
|
delete $params{HighEvent}, # WATERMARK_WRITE_EVENT_HIGH |
126
|
|
|
|
|
|
|
delete $params{LowEvent}, # WATERMARK_WRITE_EVENT_LOW |
127
|
|
|
|
|
|
|
0, # WATERMARK_WRITE_STATE |
128
|
|
|
|
|
|
|
# Driver statistics. |
129
|
|
|
|
|
|
|
0, # DRIVER_BUFFERED_OUT_OCTETS |
130
|
|
|
|
|
|
|
# Dynamic state names. |
131
|
|
|
|
|
|
|
undef, # STATE_WRITE |
132
|
|
|
|
|
|
|
undef, # STATE_READ |
133
|
|
|
|
|
|
|
# Unique ID. |
134
|
|
|
|
|
|
|
&POE::Wheel::allocate_wheel_id(), # UNIQUE_ID |
135
|
|
|
|
|
|
|
delete $params{AutoFlush}, # AUTOFLUSH |
136
|
|
|
|
|
|
|
], $type; |
137
|
|
|
|
|
|
|
|
138
|
134
|
50
|
|
|
|
356
|
if (scalar keys %params) { |
139
|
0
|
|
|
|
|
0
|
carp( |
140
|
|
|
|
|
|
|
"unknown parameters in $type constructor call: ", |
141
|
|
|
|
|
|
|
join(', ', keys %params) |
142
|
|
|
|
|
|
|
); |
143
|
|
|
|
|
|
|
} |
144
|
|
|
|
|
|
|
|
145
|
134
|
|
|
|
|
363
|
$self->_define_read_state(); |
146
|
132
|
|
|
|
|
435
|
$self->_define_write_state(); |
147
|
|
|
|
|
|
|
|
148
|
132
|
|
|
|
|
503
|
return $self; |
149
|
|
|
|
|
|
|
} |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
152
|
|
|
|
|
|
|
# Redefine the select-write handler. This uses stupid closure tricks |
153
|
|
|
|
|
|
|
# to prevent keeping extra references to $self around. |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
sub _define_write_state { |
156
|
136
|
|
|
136
|
|
175
|
my $self = shift; |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
# Read-only members. If any of these change, then the write state |
159
|
|
|
|
|
|
|
# is invalidated and needs to be redefined. |
160
|
136
|
|
|
|
|
200
|
my $driver = $self->[DRIVER_BOTH]; |
161
|
136
|
|
|
|
|
178
|
my $high_mark = $self->[WATERMARK_WRITE_MARK_HIGH]; |
162
|
136
|
|
|
|
|
154
|
my $low_mark = $self->[WATERMARK_WRITE_MARK_LOW]; |
163
|
136
|
|
|
|
|
185
|
my $event_error = \$self->[EVENT_ERROR]; |
164
|
136
|
|
|
|
|
186
|
my $event_flushed = \$self->[EVENT_FLUSHED]; |
165
|
136
|
|
|
|
|
167
|
my $event_high = \$self->[WATERMARK_WRITE_EVENT_HIGH]; |
166
|
136
|
|
|
|
|
173
|
my $event_low = \$self->[WATERMARK_WRITE_EVENT_LOW]; |
167
|
136
|
|
|
|
|
219
|
my $unique_id = $self->[UNIQUE_ID]; |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
# Read/write members. These are done by reference, to avoid pushing |
170
|
|
|
|
|
|
|
# $self into the anonymous sub. Extra copies of $self are bad and |
171
|
|
|
|
|
|
|
# can prevent wheels from destructing properly. |
172
|
136
|
|
|
|
|
159
|
my $is_in_high_water_state = \$self->[WATERMARK_WRITE_STATE]; |
173
|
136
|
|
|
|
|
190
|
my $driver_buffered_out_octets = \$self->[DRIVER_BUFFERED_OUT_OCTETS]; |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
# Register the select-write handler. |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
$poe_kernel->state( |
178
|
|
|
|
|
|
|
$self->[STATE_WRITE] = ref($self) . "($unique_id) -> select write", |
179
|
|
|
|
|
|
|
sub { # prevents SEGV |
180
|
217
|
|
|
217
|
|
219
|
0 && CRIMSON_SCOPE_HACK('<'); |
181
|
|
|
|
|
|
|
# subroutine starts here |
182
|
217
|
|
|
|
|
427
|
my ($k, $me, $handle) = @_[KERNEL, SESSION, ARG0]; |
183
|
|
|
|
|
|
|
|
184
|
217
|
|
|
|
|
623
|
$$driver_buffered_out_octets = $driver->flush($handle); |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
# When you can't write, nothing else matters. |
187
|
217
|
50
|
|
|
|
497
|
if ($!) { |
188
|
0
|
0
|
|
|
|
0
|
$$event_error && $k->call( |
189
|
|
|
|
|
|
|
$me, $$event_error, 'write', ($!+0), $!, $unique_id |
190
|
|
|
|
|
|
|
); |
191
|
0
|
|
|
|
|
0
|
$k->select_write($handle); |
192
|
|
|
|
|
|
|
} |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
# Could write, or perhaps couldn't but only because the |
195
|
|
|
|
|
|
|
# filehandle's buffer is choked. |
196
|
|
|
|
|
|
|
else { |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
# In high water state? Check for low water. High water |
199
|
|
|
|
|
|
|
# state will never be set if $event_low is undef, so don't |
200
|
|
|
|
|
|
|
# bother checking its definedness here. |
201
|
217
|
100
|
66
|
|
|
805
|
if ($$is_in_high_water_state) { |
|
|
50
|
|
|
|
|
|
202
|
4
|
50
|
|
|
|
13
|
if ( $$driver_buffered_out_octets <= $low_mark ) { |
203
|
4
|
|
|
|
|
6
|
$$is_in_high_water_state = 0; |
204
|
4
|
50
|
|
|
|
18
|
$k->call( $me, $$event_low, $unique_id ) if defined $$event_low; |
205
|
|
|
|
|
|
|
} |
206
|
|
|
|
|
|
|
} |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
# Not in high water state. Check for high water. Needs to |
209
|
|
|
|
|
|
|
# also check definedness of $$driver_buffered_out_octets. |
210
|
|
|
|
|
|
|
# Although we know this ahead of time and could probably |
211
|
|
|
|
|
|
|
# optimize it away with a second state definition, it would |
212
|
|
|
|
|
|
|
# be best to wait until ReadWrite stabilizes. That way |
213
|
|
|
|
|
|
|
# there will be only half as much code to maintain. |
214
|
|
|
|
|
|
|
elsif ( |
215
|
|
|
|
|
|
|
$high_mark and |
216
|
|
|
|
|
|
|
( $$driver_buffered_out_octets >= $high_mark ) |
217
|
|
|
|
|
|
|
) { |
218
|
0
|
|
|
|
|
0
|
$$is_in_high_water_state = 1; |
219
|
0
|
0
|
|
|
|
0
|
$k->call( $me, $$event_high, $unique_id ) if defined $$event_high; |
220
|
|
|
|
|
|
|
} |
221
|
|
|
|
|
|
|
} |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
# All chunks written; fire off a "flushed" event. This |
224
|
|
|
|
|
|
|
# occurs independently, so it's possible to get a low-water |
225
|
|
|
|
|
|
|
# call and a flushed call at the same time (if the low mark |
226
|
|
|
|
|
|
|
# is 1). |
227
|
217
|
50
|
|
|
|
474
|
unless ($$driver_buffered_out_octets) { |
228
|
217
|
|
|
|
|
572
|
$k->select_pause_write($handle); |
229
|
217
|
100
|
|
|
|
817
|
$$event_flushed && $k->call($me, $$event_flushed, $unique_id); |
230
|
|
|
|
|
|
|
} |
231
|
|
|
|
|
|
|
} |
232
|
136
|
|
|
|
|
1201
|
); |
233
|
|
|
|
|
|
|
|
234
|
136
|
|
|
|
|
438
|
$poe_kernel->select_write($self->[HANDLE_OUTPUT], $self->[STATE_WRITE]); |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
# Pause the write select immediately, unless output is pending. |
237
|
136
|
50
|
|
|
|
575
|
$poe_kernel->select_pause_write($self->[HANDLE_OUTPUT]) |
238
|
|
|
|
|
|
|
unless ($self->[DRIVER_BUFFERED_OUT_OCTETS]); |
239
|
|
|
|
|
|
|
} |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
242
|
|
|
|
|
|
|
# Redefine the select-read handler. This uses stupid closure tricks |
243
|
|
|
|
|
|
|
# to prevent keeping extra references to $self around. |
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
sub _define_read_state { |
246
|
138
|
|
|
138
|
|
201
|
my $self = shift; |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
# Register the select-read handler. |
249
|
|
|
|
|
|
|
|
250
|
138
|
100
|
|
|
|
394
|
if (defined $self->[EVENT_INPUT]) { |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
# If any of these change, then the read state is invalidated and |
253
|
|
|
|
|
|
|
# needs to be redefined. |
254
|
|
|
|
|
|
|
|
255
|
132
|
|
|
|
|
173
|
my $driver = $self->[DRIVER_BOTH]; |
256
|
132
|
|
|
|
|
212
|
my $input_filter = \$self->[FILTER_INPUT]; |
257
|
132
|
|
|
|
|
190
|
my $event_input = \$self->[EVENT_INPUT]; |
258
|
132
|
|
|
|
|
167
|
my $event_error = \$self->[EVENT_ERROR]; |
259
|
132
|
|
|
|
|
179
|
my $unique_id = $self->[UNIQUE_ID]; |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
# If the filter can get_one, then define the input state in terms |
262
|
|
|
|
|
|
|
# of get_one_start() and get_one(). |
263
|
|
|
|
|
|
|
|
264
|
132
|
50
|
33
|
|
|
1757
|
if ( |
265
|
|
|
|
|
|
|
$$input_filter->can('get_one') and |
266
|
|
|
|
|
|
|
$$input_filter->can('get_one_start') |
267
|
|
|
|
|
|
|
) { |
268
|
|
|
|
|
|
|
$poe_kernel->state( |
269
|
|
|
|
|
|
|
$self->[STATE_READ] = ref($self) . "($unique_id) -> select read", |
270
|
|
|
|
|
|
|
sub { |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
# Protects against coredump on older perls. |
273
|
285
|
|
|
285
|
|
271
|
0 && CRIMSON_SCOPE_HACK('<'); |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
# The actual code starts here. |
276
|
285
|
|
|
|
|
519
|
my ($k, $me, $handle) = @_[KERNEL, SESSION, ARG0]; |
277
|
285
|
100
|
|
|
|
800
|
if (defined(my $raw_input = $driver->get($handle))) { |
278
|
221
|
|
|
|
|
700
|
$$input_filter->get_one_start($raw_input); |
279
|
221
|
|
|
|
|
222
|
while (1) { |
280
|
434
|
|
|
|
|
1041
|
my $next_rec = $$input_filter->get_one(); |
281
|
434
|
100
|
|
|
|
1336
|
last unless @$next_rec; |
282
|
213
|
|
|
|
|
316
|
foreach my $cooked_input (@$next_rec) { |
283
|
213
|
|
|
|
|
610
|
$k->call($me, $$event_input, $cooked_input, $unique_id); |
284
|
|
|
|
|
|
|
} |
285
|
|
|
|
|
|
|
} |
286
|
|
|
|
|
|
|
} |
287
|
|
|
|
|
|
|
else { |
288
|
64
|
50
|
|
|
|
364
|
$$event_error and $k->call( |
289
|
|
|
|
|
|
|
$me, $$event_error, 'read', ($!+0), $!, $unique_id |
290
|
|
|
|
|
|
|
); |
291
|
64
|
|
|
|
|
187
|
$k->select_read($handle); |
292
|
|
|
|
|
|
|
} |
293
|
|
|
|
|
|
|
} |
294
|
132
|
|
|
|
|
1231
|
); |
295
|
|
|
|
|
|
|
} |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
# Otherwise define the input state in terms of the older, less |
298
|
|
|
|
|
|
|
# robust, yet faster get(). |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
else { |
301
|
|
|
|
|
|
|
$poe_kernel->state( |
302
|
|
|
|
|
|
|
$self->[STATE_READ] = ref($self) . "($unique_id) -> select read", |
303
|
|
|
|
|
|
|
sub { |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
# Protects against coredump on older perls. |
306
|
0
|
|
|
0
|
|
0
|
0 && CRIMSON_SCOPE_HACK('<'); |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
# The actual code starts here. |
309
|
0
|
|
|
|
|
0
|
my ($k, $me, $handle) = @_[KERNEL, SESSION, ARG0]; |
310
|
0
|
0
|
|
|
|
0
|
if (defined(my $raw_input = $driver->get($handle))) { |
311
|
0
|
|
|
|
|
0
|
foreach my $cooked_input (@{$$input_filter->get($raw_input)}) { |
|
0
|
|
|
|
|
0
|
|
312
|
0
|
|
|
|
|
0
|
$k->call($me, $$event_input, $cooked_input, $unique_id); |
313
|
|
|
|
|
|
|
} |
314
|
|
|
|
|
|
|
} |
315
|
|
|
|
|
|
|
else { |
316
|
0
|
0
|
|
|
|
0
|
$$event_error and $k->call( |
317
|
|
|
|
|
|
|
$me, $$event_error, 'read', ($!+0), $!, $unique_id |
318
|
|
|
|
|
|
|
); |
319
|
0
|
|
|
|
|
0
|
$k->select_read($handle); |
320
|
|
|
|
|
|
|
} |
321
|
|
|
|
|
|
|
} |
322
|
0
|
|
|
|
|
0
|
); |
323
|
|
|
|
|
|
|
} |
324
|
|
|
|
|
|
|
# register the state's select |
325
|
132
|
|
|
|
|
463
|
$poe_kernel->select_read($self->[HANDLE_INPUT], $self->[STATE_READ]); |
326
|
|
|
|
|
|
|
} |
327
|
|
|
|
|
|
|
# undefine the select, just in case |
328
|
|
|
|
|
|
|
else { |
329
|
6
|
|
|
|
|
24
|
$poe_kernel->select_read($self->[HANDLE_INPUT]) |
330
|
|
|
|
|
|
|
} |
331
|
|
|
|
|
|
|
} |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
334
|
|
|
|
|
|
|
# Redefine events. |
335
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
sub event { |
337
|
4
|
|
|
4
|
1
|
36
|
my $self = shift; |
338
|
4
|
50
|
|
|
|
14
|
push(@_, undef) if (scalar(@_) & 1); |
339
|
|
|
|
|
|
|
|
340
|
4
|
|
|
|
|
9
|
my ($redefine_read, $redefine_write) = (0, 0); |
341
|
|
|
|
|
|
|
|
342
|
4
|
|
|
|
|
789
|
while (@_) { |
343
|
14
|
|
|
|
|
21
|
my ($name, $event) = splice(@_, 0, 2); |
344
|
|
|
|
|
|
|
|
345
|
14
|
100
|
|
|
|
53
|
if ($name eq 'InputEvent') { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
346
|
2
|
|
|
|
|
3
|
$self->[EVENT_INPUT] = $event; |
347
|
2
|
|
|
|
|
6
|
$redefine_read = 1; |
348
|
|
|
|
|
|
|
} |
349
|
|
|
|
|
|
|
elsif ($name eq 'ErrorEvent') { |
350
|
4
|
|
|
|
|
9
|
$self->[EVENT_ERROR] = $event; |
351
|
4
|
|
|
|
|
9
|
$redefine_read = $redefine_write = 1; |
352
|
|
|
|
|
|
|
} |
353
|
|
|
|
|
|
|
elsif ($name eq 'FlushedEvent') { |
354
|
4
|
|
|
|
|
7
|
$self->[EVENT_FLUSHED] = $event; |
355
|
4
|
|
|
|
|
11
|
$redefine_write = 1; |
356
|
|
|
|
|
|
|
} |
357
|
|
|
|
|
|
|
elsif ($name eq 'HighEvent') { |
358
|
2
|
50
|
|
|
|
742
|
if (defined $self->[WATERMARK_WRITE_MARK_HIGH]) { |
359
|
2
|
|
|
|
|
5
|
$self->[WATERMARK_WRITE_EVENT_HIGH] = $event; |
360
|
2
|
|
|
|
|
7
|
$redefine_write = 1; |
361
|
|
|
|
|
|
|
} |
362
|
|
|
|
|
|
|
else { |
363
|
0
|
|
|
|
|
0
|
carp "Ignoring HighEvent (there is no high watermark set)"; |
364
|
|
|
|
|
|
|
} |
365
|
|
|
|
|
|
|
} |
366
|
|
|
|
|
|
|
elsif ($name eq 'LowEvent') { |
367
|
2
|
50
|
|
|
|
5
|
if (defined $self->[WATERMARK_WRITE_MARK_LOW]) { |
368
|
2
|
|
|
|
|
2
|
$self->[WATERMARK_WRITE_EVENT_LOW] = $event; |
369
|
2
|
|
|
|
|
6
|
$redefine_write = 1; |
370
|
|
|
|
|
|
|
} |
371
|
|
|
|
|
|
|
else { |
372
|
0
|
|
|
|
|
0
|
carp "Ignoring LowEvent (there is no high watermark set)"; |
373
|
|
|
|
|
|
|
} |
374
|
|
|
|
|
|
|
} |
375
|
|
|
|
|
|
|
else { |
376
|
0
|
|
|
|
|
0
|
carp "ignoring unknown ReadWrite parameter '$name'"; |
377
|
|
|
|
|
|
|
} |
378
|
|
|
|
|
|
|
} |
379
|
|
|
|
|
|
|
|
380
|
4
|
50
|
|
|
|
18
|
$self->_define_read_state() if $redefine_read; |
381
|
4
|
50
|
|
|
|
21
|
$self->_define_write_state() if $redefine_write; |
382
|
|
|
|
|
|
|
} |
383
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
385
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
sub DESTROY { |
387
|
134
|
|
|
134
|
|
3752
|
my $self = shift; |
388
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
# Turn off the select. This is a problem if a wheel is being |
390
|
|
|
|
|
|
|
# swapped, since it will turn off selects for the other wheel. |
391
|
134
|
50
|
|
|
|
352
|
if ($self->[HANDLE_INPUT]) { |
392
|
134
|
|
|
|
|
392
|
$poe_kernel->select_read($self->[HANDLE_INPUT]); |
393
|
132
|
|
|
|
|
205
|
$self->[HANDLE_INPUT] = undef; |
394
|
|
|
|
|
|
|
} |
395
|
|
|
|
|
|
|
|
396
|
132
|
50
|
|
|
|
346
|
if ($self->[HANDLE_OUTPUT]) { |
397
|
132
|
|
|
|
|
761
|
$poe_kernel->select_write($self->[HANDLE_OUTPUT]); |
398
|
132
|
|
|
|
|
209
|
$self->[HANDLE_OUTPUT] = undef; |
399
|
|
|
|
|
|
|
} |
400
|
|
|
|
|
|
|
|
401
|
132
|
100
|
|
|
|
4153
|
if ($self->[STATE_READ]) { |
402
|
130
|
|
|
|
|
433
|
$poe_kernel->state($self->[STATE_READ]); |
403
|
130
|
|
|
|
|
194
|
$self->[STATE_READ] = undef; |
404
|
|
|
|
|
|
|
} |
405
|
|
|
|
|
|
|
|
406
|
132
|
50
|
|
|
|
308
|
if ($self->[STATE_WRITE]) { |
407
|
132
|
|
|
|
|
303
|
$poe_kernel->state($self->[STATE_WRITE]); |
408
|
132
|
|
|
|
|
212
|
$self->[STATE_WRITE] = undef; |
409
|
|
|
|
|
|
|
} |
410
|
|
|
|
|
|
|
|
411
|
132
|
|
|
|
|
521
|
&POE::Wheel::free_wheel_id($self->[UNIQUE_ID]); |
412
|
|
|
|
|
|
|
} |
413
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
415
|
|
|
|
|
|
|
# TODO - We set the high/low watermark state here, but we don't fire |
416
|
|
|
|
|
|
|
# events for it. My assumption is that the return value tells us |
417
|
|
|
|
|
|
|
# all we want to know. |
418
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
sub put { |
420
|
247
|
|
|
247
|
1
|
6273
|
my ($self, @chunks) = @_; |
421
|
|
|
|
|
|
|
|
422
|
247
|
|
|
|
|
330
|
my $old_buffered_out_octets = $self->[DRIVER_BUFFERED_OUT_OCTETS]; |
423
|
247
|
|
|
|
|
805
|
my $new_buffered_out_octets = |
424
|
|
|
|
|
|
|
$self->[DRIVER_BUFFERED_OUT_OCTETS] = |
425
|
|
|
|
|
|
|
$self->[DRIVER_BOTH]->put($self->[FILTER_OUTPUT]->put(\@chunks)); |
426
|
|
|
|
|
|
|
|
427
|
247
|
0
|
33
|
|
|
667
|
if ( |
|
|
|
33
|
|
|
|
|
428
|
|
|
|
|
|
|
$self->[AUTOFLUSH] && |
429
|
|
|
|
|
|
|
$new_buffered_out_octets and !$old_buffered_out_octets |
430
|
|
|
|
|
|
|
) { |
431
|
0
|
|
|
|
|
0
|
$old_buffered_out_octets = $new_buffered_out_octets; |
432
|
0
|
|
|
|
|
0
|
$self->flush(); |
433
|
0
|
|
|
|
|
0
|
$new_buffered_out_octets = $self->[DRIVER_BUFFERED_OUT_OCTETS]; |
434
|
|
|
|
|
|
|
} |
435
|
|
|
|
|
|
|
|
436
|
|
|
|
|
|
|
# Resume write-ok if the output buffer gets data. This avoids |
437
|
|
|
|
|
|
|
# redundant calls to select_resume_write(), which is probably a good |
438
|
|
|
|
|
|
|
# thing. |
439
|
247
|
100
|
66
|
|
|
872
|
if ($new_buffered_out_octets and !$old_buffered_out_octets) { |
440
|
219
|
|
|
|
|
639
|
$poe_kernel->select_resume_write($self->[HANDLE_OUTPUT]); |
441
|
|
|
|
|
|
|
} |
442
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
# If the high watermark has been reached, return true. |
444
|
247
|
100
|
100
|
|
|
680
|
if ( |
445
|
|
|
|
|
|
|
$self->[WATERMARK_WRITE_MARK_HIGH] and |
446
|
|
|
|
|
|
|
$new_buffered_out_octets >= $self->[WATERMARK_WRITE_MARK_HIGH] |
447
|
|
|
|
|
|
|
) { |
448
|
8
|
|
|
|
|
20
|
return $self->[WATERMARK_WRITE_STATE] = 1; |
449
|
|
|
|
|
|
|
} |
450
|
|
|
|
|
|
|
|
451
|
239
|
|
|
|
|
684
|
return $self->[WATERMARK_WRITE_STATE] = 0; |
452
|
|
|
|
|
|
|
} |
453
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
455
|
|
|
|
|
|
|
# Redefine filter. -PG / Now that there are two filters internally, |
456
|
|
|
|
|
|
|
# one input and one output, make this set both of them at the same |
457
|
|
|
|
|
|
|
# time. -RCC |
458
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
sub _transfer_input_buffer { |
460
|
41
|
|
|
41
|
|
52
|
my ($self, $buf) = @_; |
461
|
|
|
|
|
|
|
|
462
|
41
|
|
|
|
|
48
|
my $old_input_filter = $self->[FILTER_INPUT]; |
463
|
|
|
|
|
|
|
|
464
|
|
|
|
|
|
|
# If the new filter implements "get_one", use that. |
465
|
41
|
50
|
33
|
|
|
276
|
if ( |
466
|
|
|
|
|
|
|
$old_input_filter->can('get_one') and |
467
|
|
|
|
|
|
|
$old_input_filter->can('get_one_start') |
468
|
|
|
|
|
|
|
) { |
469
|
41
|
100
|
|
|
|
89
|
if (defined $buf) { |
470
|
9
|
|
|
|
|
17
|
$self->[FILTER_INPUT]->get_one_start($buf); |
471
|
9
|
|
|
|
|
21
|
while ($self->[FILTER_INPUT] == $old_input_filter) { |
472
|
19
|
|
|
|
|
46
|
my $next_rec = $self->[FILTER_INPUT]->get_one(); |
473
|
19
|
100
|
|
|
|
39
|
last unless @$next_rec; |
474
|
18
|
|
|
|
|
25
|
foreach my $cooked_input (@$next_rec) { |
475
|
18
|
|
|
|
|
42
|
$poe_kernel->call( |
476
|
|
|
|
|
|
|
$poe_kernel->get_active_session(), |
477
|
|
|
|
|
|
|
$self->[EVENT_INPUT], |
478
|
|
|
|
|
|
|
$cooked_input, $self->[UNIQUE_ID] |
479
|
|
|
|
|
|
|
); |
480
|
|
|
|
|
|
|
} |
481
|
|
|
|
|
|
|
} |
482
|
|
|
|
|
|
|
} |
483
|
|
|
|
|
|
|
} |
484
|
|
|
|
|
|
|
|
485
|
|
|
|
|
|
|
# Otherwise use the old behavior. |
486
|
|
|
|
|
|
|
else { |
487
|
0
|
0
|
|
|
|
0
|
if (defined $buf) { |
488
|
0
|
|
|
|
|
0
|
foreach my $cooked_input (@{$self->[FILTER_INPUT]->get($buf)}) { |
|
0
|
|
|
|
|
0
|
|
489
|
0
|
|
|
|
|
0
|
$poe_kernel->call( |
490
|
|
|
|
|
|
|
$poe_kernel->get_active_session(), |
491
|
|
|
|
|
|
|
$self->[EVENT_INPUT], |
492
|
|
|
|
|
|
|
$cooked_input, $self->[UNIQUE_ID] |
493
|
|
|
|
|
|
|
); |
494
|
|
|
|
|
|
|
} |
495
|
|
|
|
|
|
|
} |
496
|
|
|
|
|
|
|
} |
497
|
|
|
|
|
|
|
} |
498
|
|
|
|
|
|
|
|
499
|
|
|
|
|
|
|
# Set input and output filters. |
500
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
sub set_filter { |
502
|
32
|
|
|
32
|
1
|
38
|
my ($self, $new_filter) = @_; |
503
|
32
|
|
|
|
|
84
|
my $buf = $self->[FILTER_INPUT]->get_pending(); |
504
|
32
|
|
|
|
|
48
|
$self->[FILTER_INPUT] = $self->[FILTER_OUTPUT] = $new_filter; |
505
|
|
|
|
|
|
|
|
506
|
32
|
|
|
|
|
95
|
$self->_transfer_input_buffer($buf); |
507
|
|
|
|
|
|
|
} |
508
|
|
|
|
|
|
|
|
509
|
|
|
|
|
|
|
# Redefine input and/or output filters separately. |
510
|
|
|
|
|
|
|
sub set_input_filter { |
511
|
9
|
|
|
9
|
1
|
10
|
my ($self, $new_filter) = @_; |
512
|
9
|
|
|
|
|
23
|
my $buf = $self->[FILTER_INPUT]->get_pending(); |
513
|
9
|
|
|
|
|
11
|
$self->[FILTER_INPUT] = $new_filter; |
514
|
|
|
|
|
|
|
|
515
|
9
|
|
|
|
|
46
|
$self->_transfer_input_buffer($buf); |
516
|
|
|
|
|
|
|
} |
517
|
|
|
|
|
|
|
|
518
|
|
|
|
|
|
|
# No closures need to be redefined or anything. All the previously |
519
|
|
|
|
|
|
|
# put stuff has been serialized already. |
520
|
|
|
|
|
|
|
sub set_output_filter { |
521
|
9
|
|
|
9
|
1
|
10
|
my ($self, $new_filter) = @_; |
522
|
9
|
|
|
|
|
32
|
$self->[FILTER_OUTPUT] = $new_filter; |
523
|
|
|
|
|
|
|
} |
524
|
|
|
|
|
|
|
|
525
|
|
|
|
|
|
|
# Get the current input filter; used for accessing the filter's custom |
526
|
|
|
|
|
|
|
# methods, as in: $wheel->get_input_filter()->filter_method(); |
527
|
|
|
|
|
|
|
sub get_input_filter { |
528
|
2
|
|
|
2
|
1
|
33
|
my $self = shift; |
529
|
2
|
|
|
|
|
11
|
return $self->[FILTER_INPUT]; |
530
|
|
|
|
|
|
|
} |
531
|
|
|
|
|
|
|
|
532
|
|
|
|
|
|
|
# Get the current input filter; used for accessing the filter's custom |
533
|
|
|
|
|
|
|
# methods, as in: $wheel->get_input_filter()->filter_method(); |
534
|
|
|
|
|
|
|
sub get_output_filter { |
535
|
2
|
|
|
2
|
1
|
2
|
my $self = shift; |
536
|
2
|
|
|
|
|
7
|
return $self->[FILTER_OUTPUT]; |
537
|
|
|
|
|
|
|
} |
538
|
|
|
|
|
|
|
|
539
|
|
|
|
|
|
|
# Set the high water mark. |
540
|
|
|
|
|
|
|
|
541
|
|
|
|
|
|
|
sub set_high_mark { |
542
|
0
|
|
|
0
|
1
|
0
|
my ($self, $new_high_mark) = @_; |
543
|
|
|
|
|
|
|
|
544
|
0
|
0
|
|
|
|
0
|
unless (defined $self->[WATERMARK_WRITE_MARK_HIGH]) { |
545
|
0
|
|
|
|
|
0
|
carp "Ignoring high mark (must be initialized in constructor first)"; |
546
|
0
|
|
|
|
|
0
|
return; |
547
|
|
|
|
|
|
|
} |
548
|
|
|
|
|
|
|
|
549
|
0
|
0
|
|
|
|
0
|
unless (defined $new_high_mark) { |
550
|
0
|
|
|
|
|
0
|
carp "New high mark is undefined. Ignored"; |
551
|
0
|
|
|
|
|
0
|
return; |
552
|
|
|
|
|
|
|
} |
553
|
|
|
|
|
|
|
|
554
|
0
|
0
|
|
|
|
0
|
unless ($new_high_mark > $self->[WATERMARK_WRITE_MARK_LOW]) { |
555
|
0
|
|
|
|
|
0
|
carp "New high mark would not be greater than low mark. Ignored"; |
556
|
0
|
|
|
|
|
0
|
return; |
557
|
|
|
|
|
|
|
} |
558
|
|
|
|
|
|
|
|
559
|
0
|
|
|
|
|
0
|
$self->[WATERMARK_WRITE_MARK_HIGH] = $new_high_mark; |
560
|
0
|
|
|
|
|
0
|
$self->_define_write_state(); |
561
|
|
|
|
|
|
|
} |
562
|
|
|
|
|
|
|
|
563
|
|
|
|
|
|
|
sub set_low_mark { |
564
|
0
|
|
|
0
|
1
|
0
|
my ($self, $new_low_mark) = @_; |
565
|
|
|
|
|
|
|
|
566
|
0
|
0
|
|
|
|
0
|
unless (defined $self->[WATERMARK_WRITE_MARK_LOW]) { |
567
|
0
|
|
|
|
|
0
|
carp "Ignoring low mark (must be initialized in constructor first)"; |
568
|
0
|
|
|
|
|
0
|
return; |
569
|
|
|
|
|
|
|
} |
570
|
|
|
|
|
|
|
|
571
|
0
|
0
|
|
|
|
0
|
unless (defined $new_low_mark) { |
572
|
0
|
|
|
|
|
0
|
carp "New low mark is undefined. Ignored"; |
573
|
0
|
|
|
|
|
0
|
return; |
574
|
|
|
|
|
|
|
} |
575
|
|
|
|
|
|
|
|
576
|
0
|
0
|
|
|
|
0
|
unless ($new_low_mark > 0) { |
577
|
0
|
|
|
|
|
0
|
carp "New low mark would be less than one. Ignored"; |
578
|
0
|
|
|
|
|
0
|
return; |
579
|
|
|
|
|
|
|
} |
580
|
|
|
|
|
|
|
|
581
|
0
|
0
|
|
|
|
0
|
unless ($new_low_mark < $self->[WATERMARK_WRITE_MARK_HIGH]) { |
582
|
0
|
|
|
|
|
0
|
carp "New low mark would not be less than high high mark. Ignored"; |
583
|
0
|
|
|
|
|
0
|
return; |
584
|
|
|
|
|
|
|
} |
585
|
|
|
|
|
|
|
|
586
|
0
|
|
|
|
|
0
|
$self->[WATERMARK_WRITE_MARK_LOW] = $new_low_mark; |
587
|
0
|
|
|
|
|
0
|
$self->_define_write_state(); |
588
|
|
|
|
|
|
|
} |
589
|
|
|
|
|
|
|
|
590
|
|
|
|
|
|
|
# Return driver statistics. |
591
|
|
|
|
|
|
|
sub get_driver_out_octets { |
592
|
56
|
|
|
56
|
1
|
300
|
$_[0]->[DRIVER_BUFFERED_OUT_OCTETS]; |
593
|
|
|
|
|
|
|
} |
594
|
|
|
|
|
|
|
|
595
|
|
|
|
|
|
|
sub get_driver_out_messages { |
596
|
4
|
|
|
4
|
1
|
28
|
$_[0]->[DRIVER_BOTH]->get_out_messages_buffered(); |
597
|
|
|
|
|
|
|
} |
598
|
|
|
|
|
|
|
|
599
|
|
|
|
|
|
|
# Get the wheel's ID. |
600
|
|
|
|
|
|
|
sub ID { |
601
|
12
|
|
|
12
|
1
|
100
|
return $_[0]->[UNIQUE_ID]; |
602
|
|
|
|
|
|
|
} |
603
|
|
|
|
|
|
|
|
604
|
|
|
|
|
|
|
# Pause the wheel's input watcher. |
605
|
|
|
|
|
|
|
sub pause_input { |
606
|
2
|
|
|
2
|
1
|
757
|
my $self = shift; |
607
|
2
|
50
|
|
|
|
8
|
return unless defined $self->[HANDLE_INPUT]; |
608
|
2
|
|
|
|
|
10
|
$poe_kernel->select_pause_read( $self->[HANDLE_INPUT] ); |
609
|
|
|
|
|
|
|
} |
610
|
|
|
|
|
|
|
|
611
|
|
|
|
|
|
|
# Resume the wheel's input watcher. |
612
|
|
|
|
|
|
|
sub resume_input { |
613
|
2
|
|
|
2
|
1
|
20
|
my $self = shift; |
614
|
2
|
50
|
|
|
|
8
|
return unless defined $self->[HANDLE_INPUT]; |
615
|
2
|
|
|
|
|
10
|
$poe_kernel->select_resume_read( $self->[HANDLE_INPUT] ); |
616
|
|
|
|
|
|
|
} |
617
|
|
|
|
|
|
|
|
618
|
|
|
|
|
|
|
# Return the wheel's input handle |
619
|
|
|
|
|
|
|
sub get_input_handle { |
620
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
621
|
0
|
|
|
|
|
0
|
return $self->[HANDLE_INPUT]; |
622
|
|
|
|
|
|
|
} |
623
|
|
|
|
|
|
|
|
624
|
|
|
|
|
|
|
# Return the wheel's output handle |
625
|
|
|
|
|
|
|
sub get_output_handle { |
626
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
627
|
0
|
|
|
|
|
0
|
return $self->[HANDLE_OUTPUT]; |
628
|
|
|
|
|
|
|
} |
629
|
|
|
|
|
|
|
|
630
|
|
|
|
|
|
|
# Shutdown the socket for reading. |
631
|
|
|
|
|
|
|
sub shutdown_input { |
632
|
2
|
|
|
2
|
1
|
25
|
my $self = shift; |
633
|
2
|
50
|
|
|
|
6
|
return unless defined $self->[HANDLE_INPUT]; |
634
|
2
|
|
|
|
|
3
|
eval { local $^W = 0; shutdown($self->[HANDLE_INPUT], 0) }; |
|
2
|
|
|
|
|
8
|
|
|
2
|
|
|
|
|
37
|
|
635
|
2
|
|
|
|
|
8
|
$poe_kernel->select_read($self->[HANDLE_INPUT], undef); |
636
|
|
|
|
|
|
|
} |
637
|
|
|
|
|
|
|
|
638
|
|
|
|
|
|
|
# Shutdown the socket for writing. |
639
|
|
|
|
|
|
|
sub shutdown_output { |
640
|
2
|
|
|
2
|
1
|
14
|
my $self = shift; |
641
|
2
|
50
|
|
|
|
11
|
return unless defined $self->[HANDLE_OUTPUT]; |
642
|
2
|
|
|
|
|
5
|
eval { local $^W=0; shutdown($self->[HANDLE_OUTPUT], 1) }; |
|
2
|
|
|
|
|
9
|
|
|
2
|
|
|
|
|
9
|
|
643
|
2
|
|
|
|
|
11
|
$poe_kernel->select_write($self->[HANDLE_OUTPUT], undef); |
644
|
|
|
|
|
|
|
} |
645
|
|
|
|
|
|
|
|
646
|
|
|
|
|
|
|
# Flush the output handle |
647
|
|
|
|
|
|
|
sub flush { |
648
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
649
|
0
|
0
|
|
|
|
|
return unless defined $self->[HANDLE_OUTPUT]; |
650
|
0
|
|
|
|
|
|
$poe_kernel->call($poe_kernel->get_active_session(), |
651
|
|
|
|
|
|
|
$self->[STATE_WRITE], $self->[HANDLE_OUTPUT]); |
652
|
|
|
|
|
|
|
} |
653
|
|
|
|
|
|
|
|
654
|
|
|
|
|
|
|
1; |
655
|
|
|
|
|
|
|
|
656
|
|
|
|
|
|
|
__END__ |