File Coverage

blib/lib/MCE/Shared/Handle.pm
Criterion Covered Total %
statement 176 296 59.4
branch 50 178 28.0
condition 15 75 20.0
subroutine 32 49 65.3
pod 1 1 100.0
total 274 599 45.7


line stmt bran cond sub pod time code
1             ###############################################################################
2             ## ----------------------------------------------------------------------------
3             ## Handle helper class.
4             ##
5             ###############################################################################
6              
7             package MCE::Shared::Handle;
8              
9 2     2   2987 use strict;
  2         3  
  2         52  
10 2     2   9 use warnings;
  2         2  
  2         43  
11              
12 2     2   34 use 5.010001;
  2         6  
13              
14 2     2   8 no warnings qw( threads recursion uninitialized numeric );
  2         4  
  2         109  
15              
16             our $VERSION = '1.885';
17              
18             ## no critic (BuiltinFunctions::ProhibitStringyEval)
19             ## no critic (InputOutput::ProhibitTwoArgOpen)
20             ## no critic (Subroutines::ProhibitExplicitReturnUndef)
21             ## no critic (Subroutines::ProhibitSubroutinePrototypes)
22             ## no critic (TestingAndDebugging::ProhibitNoStrict)
23              
24 2     2   19 use MCE::Shared::Base ();
  2         3  
  2         308  
25              
26             my $LF = "\012"; Internals::SvREADONLY($LF, 1);
27             my $_tid = $INC{'threads.pm'} ? threads->tid() : 0;
28             my $_max_fd = eval 'fileno(\*main::DATA)' // 2;
29             my $_reset_flg = 1;
30              
31             sub _croak {
32 0     0   0 goto &MCE::Shared::Base::_croak;
33             }
34             sub CLONE {
35 0 0   0   0 $_tid = threads->tid() if $INC{'threads.pm'};
36             }
37              
38             sub import {
39 2 50   2   17 if (!defined $INC{'MCE/Shared.pm'}) {
40 2     2   13 no strict 'refs'; no warnings 'redefine';
  2     2   3  
  2         57  
  2         16  
  2         5  
  2         279  
41 0         0 *{ caller().'::mce_open' } = \&open;
  0         0  
42             }
43 2         18 return;
44             }
45              
46             sub TIEHANDLE {
47 3     3   9 my $class = shift;
48              
49 3 50       17 if (ref $_[0] eq 'ARRAY') {
50             # For use with MCE::Shared in order to reach the Server process.
51             # Therefore constructed without a GLOB handle initially.
52              
53             MCE::Shared::Object::_reset(), $_reset_flg = ''
54 3 50 66     26 if $_reset_flg && $INC{'MCE/Shared/Server.pm'};
55              
56 3         31 return bless $_[0], $class;
57             }
58              
59 2     2   12 bless my $fh = \do { no warnings 'once'; local *FH }, $class;
  2         2  
  2         1043  
  0         0  
  0         0  
60              
61 0 0       0 if (@_) {
62 0 0       0 if ( !defined wantarray ) {
63 0 0       0 $fh->OPEN(@_) or _croak("open error: $!");
64             } else {
65 0 0       0 $fh->OPEN(@_) or return '';
66             }
67             }
68              
69 0         0 $fh;
70             }
71              
72             ###############################################################################
73             ## ----------------------------------------------------------------------------
74             ## Based on Tie::StdHandle.
75             ##
76             ###############################################################################
77              
78 0     0   0 sub EOF { eof($_[0]) }
79 0     0   0 sub TELL { tell($_[0]) }
80 0     0   0 sub FILENO { fileno($_[0]) }
81 0     0   0 sub SEEK { seek($_[0], $_[1], $_[2]) }
82 0 0   0   0 sub CLOSE { close($_[0]) if defined(fileno $_[0]) }
83 0 0 0 0   0 sub BINMODE { binmode($_[0], $_[1] // ':raw') ? 1 : '' }
84 0     0   0 sub GETC { getc($_[0]) }
85              
86             sub OPEN {
87 0     0   0 my $ret;
88              
89 0 0       0 close($_[0]) if defined fileno($_[0]);
90              
91 0 0 0     0 if ( @_ == 3 && ref $_[2] && defined( my $_fd = fileno($_[2]) ) ) {
      0        
92 0         0 $ret = CORE::open($_[0], $_[1]."&=$_fd");
93             }
94             else {
95 0 0       0 $ret = ( @_ == 2 )
96             ? CORE::open($_[0], $_[1])
97             : CORE::open($_[0], $_[1], $_[2]);
98             }
99              
100             # enable autoflush
101 0 0       0 select(( select($_[0]), $| = 1 )[0]) if $ret;
102              
103 0         0 $ret;
104             }
105              
106             sub open (@) {
107 0 0 0 0 1 0 shift if ( defined $_[0] && $_[0] eq 'MCE::Shared::Handle' );
108              
109 0         0 my $item;
110              
111 0 0 0     0 if ( ref $_[0] eq 'GLOB' && tied *{ $_[0] } &&
  0 0 0     0  
112 0         0 ref tied(*{ $_[0] }) eq __PACKAGE__ ) {
113 0         0 $item = tied *{ $_[0] };
  0         0  
114             }
115             elsif ( @_ ) {
116 0 0 0     0 if ( ref $_[0] eq 'GLOB' && tied *{ $_[0] } ) {
  0         0  
117 0 0       0 close $_[0] if defined ( fileno $_[0] );
118             }
119 2     2   19 $_[0] = \do { no warnings 'once'; local *FH };
  2         4  
  2         1232  
  0         0  
  0         0  
120 0         0 $item = tie *{ $_[0] }, __PACKAGE__;
  0         0  
121             }
122              
123 0 0       0 shift; _croak("Not enough arguments for open") unless @_;
  0         0  
124              
125 0 0       0 if ( !defined wantarray ) {
126 0 0       0 $item->OPEN(@_) or _croak("open error: $!");
127             } else {
128 0         0 $item->OPEN(@_);
129             }
130             }
131              
132             sub READ {
133 0     0   0 my ($fh, $len, $auto) = ($_[0], $_[2]);
134              
135 0 0       0 if (lc(substr $len, -1, 1) eq 'm') {
    0          
136 0         0 $auto = 1, chop $len; $len *= 1024 * 1024;
  0         0  
137             } elsif (lc(substr $len, -1, 1) eq 'k') {
138 0         0 $auto = 1, chop $len; $len *= 1024;
  0         0  
139             }
140              
141             # normal use-case
142              
143 0 0       0 if (!$auto) {
144 0 0       0 return @_ == 4 ? read($fh, $_[1], $len, $_[3]) : read($fh, $_[1], $len);
145             }
146              
147             # chunk IO, read up to record separator or eof
148             # support special case; e.g. $/ = "\n>" for bioinformatics
149             # anchoring ">" at the start of line
150              
151 0         0 my ($tmp, $ret);
152              
153 0 0       0 if (!eof($fh)) {
154 0 0 0     0 if (length $/ > 1 && substr($/, 0, 1) eq "\n") {
    0          
155 0         0 my $len = length($/) - 1;
156              
157 0 0       0 if (tell $fh) {
158 0         0 $tmp = substr($/, 1);
159 0         0 $ret = read($fh, $tmp, $len, length($tmp));
160             } else {
161 0         0 $ret = read($fh, $tmp, $len);
162             }
163              
164 0 0       0 if (defined $ret) {
165 0 0       0 $. += 1 if eof($fh);
166 0         0 $tmp .= readline($fh);
167              
168 0 0       0 substr($tmp, -$len, $len, '')
169             if (substr($tmp, -$len) eq substr($/, 1));
170             }
171             }
172             elsif (defined ($ret = CORE::read($fh, $tmp, $len))) {
173 0 0       0 $. += 1 if eof($fh);
174 0         0 $tmp .= readline($fh);
175             }
176             }
177             else {
178 0         0 $tmp = '', $ret = 0;
179             }
180              
181 0 0       0 if (defined $ret) {
182 0   0     0 my $pos = $_[3] || 0;
183 0         0 substr($_[1], $pos, length($_[1]) - $pos, $tmp);
184 0         0 length($tmp);
185             }
186             else {
187 0         0 undef;
188             }
189             }
190              
191             sub READLINE {
192             # support special case; e.g. $/ = "\n>" for bioinformatics
193             # anchoring ">" at the start of line
194              
195 0 0 0 0   0 if (length $/ > 1 && substr($/, 0, 1) eq "\n" && !eof($_[0])) {
      0        
196 0         0 my ($len, $buf) = (length($/) - 1);
197              
198 0 0       0 if (tell $_[0]) {
199 0         0 $buf = substr($/, 1), $buf .= readline($_[0]);
200             } else {
201 0         0 $buf = readline($_[0]);
202             }
203              
204 0 0       0 substr($buf, -$len, $len, '')
205             if (substr($buf, -$len) eq substr($/, 1));
206              
207 0         0 $buf;
208             }
209             else {
210 0         0 scalar(readline($_[0]));
211             }
212             }
213              
214             sub PRINT {
215 0     0   0 my $fh = shift;
216 0 0       0 my $buf = join(defined $, ? $, : "", @_);
217 0 0       0 $buf .= $\ if defined $\;
218 0         0 local $\; # don't print any line terminator
219 0         0 print $fh $buf;
220             }
221              
222             sub PRINTF {
223 0     0   0 my $fh = shift;
224 0         0 my $buf = sprintf(shift, @_);
225 0         0 local $\; # ditto
226 0         0 print $fh $buf;
227             }
228              
229             sub WRITE {
230 2     2   13 use bytes;
  2         3  
  2         12  
231              
232             # based on IO::SigGuard::syswrite 0.011 by Felipe Gasper (FELIPE)
233 0     0   0 my $wrote = 0;
234              
235             WRITE: {
236 0         0 $wrote += (
237             ( @_ == 2 )
238             ? syswrite($_[0], $_[1], length($_[1]) - $wrote, $wrote)
239             : ( @_ == 3 )
240             ? syswrite($_[0], $_[1], $_[2] - $wrote, $wrote)
241             : syswrite($_[0], $_[1], $_[2] - $wrote, $_[3] + $wrote)
242 0 0       0 ) or do {
    0          
    0          
243 0 0       0 unless ( defined $wrote ) {
244 0 0 0     0 redo WRITE if $!{EINTR} || $!{EAGAIN} || $!{EWOULDBLOCK};
      0        
245 0         0 return undef;
246             }
247             };
248             }
249              
250 0         0 $wrote;
251             }
252              
253             {
254 2     2   325 no strict 'refs'; *{ __PACKAGE__.'::new' } = \&TIEHANDLE;
  2         3  
  2         152  
255             }
256              
257             ###############################################################################
258             ## ----------------------------------------------------------------------------
259             ## Server functions.
260             ##
261             ###############################################################################
262              
263             {
264             use constant {
265 2         2250 SHR_O_CLO => 'O~CLO', # Handle CLOSE
266             SHR_O_OPN => 'O~OPN', # Handle OPEN
267             SHR_O_REA => 'O~REA', # Handle READ
268             SHR_O_RLN => 'O~RLN', # Handle READLINE
269             SHR_O_PRI => 'O~PRI', # Handle PRINT
270             SHR_O_WRI => 'O~WRI', # Handle WRITE
271 2     2   12 };
  2         3  
272              
273             my (
274             $_DAU_R_SOCK_REF, $_DAU_R_SOCK, $_obj, $_freeze, $_thaw,
275             $_id, $_len, $_ret
276             );
277              
278             my %_output_function = (
279              
280             SHR_O_CLO.$LF => sub { # Handle CLOSE
281             $_DAU_R_SOCK = ${ $_DAU_R_SOCK_REF };
282             chomp($_id = <$_DAU_R_SOCK>);
283              
284             close $_obj->{ $_id } if defined fileno($_obj->{ $_id });
285             print {$_DAU_R_SOCK} '1'.$LF;
286              
287             return;
288             },
289              
290             SHR_O_OPN.$LF => sub { # Handle OPEN
291             $_DAU_R_SOCK = ${ $_DAU_R_SOCK_REF };
292             my ($_fd, $_buf, $_err); local $!;
293              
294             chomp($_id = <$_DAU_R_SOCK>),
295             chomp($_fd = <$_DAU_R_SOCK>),
296             chomp($_len = <$_DAU_R_SOCK>),
297              
298             read($_DAU_R_SOCK, $_buf, $_len);
299             print {$_DAU_R_SOCK} $LF;
300              
301             if ($_fd > $_max_fd) {
302             $_fd = IO::FDPass::recv(fileno $_DAU_R_SOCK); $_fd >= 0
303             or _croak("cannot receive file handle: $!");
304             }
305              
306             close $_obj->{ $_id } if defined fileno($_obj->{ $_id });
307              
308             my $_args = $_thaw->($_buf);
309             my $_fh;
310              
311             if (@{ $_args } == 2) {
312             # remove tainted'ness from $_args
313             ($_args->[0]) = $_args->[0] =~ /(.*)/;
314             ($_args->[1]) = $_args->[1] =~ /(.*)/;
315              
316             CORE::open($_fh, "$_args->[0]", $_args->[1]) or do { $_err = 0+$! };
317             }
318             else {
319             # remove tainted'ness from $_args
320             ($_args->[0]) = $_args->[0] =~ /(.*)/;
321              
322             CORE::open($_fh, $_args->[0]) or do { $_err = 0+$! };
323             }
324              
325             # enable autoflush
326             select(( select($_fh), $| = 1 )[0]) unless $_err;
327              
328             *{ $_obj->{ $_id } } = *{ $_fh };
329             print {$_DAU_R_SOCK} $_err.$LF;
330              
331             return;
332             },
333              
334             SHR_O_REA.$LF => sub { # Handle READ
335             $_DAU_R_SOCK = ${ $_DAU_R_SOCK_REF };
336             my ($_a3, $_auto);
337              
338             chomp($_id = <$_DAU_R_SOCK>),
339             chomp($_a3 = <$_DAU_R_SOCK>),
340             chomp($_len = <$_DAU_R_SOCK>);
341              
342             if (lc(substr $_a3, -1, 1) eq 'm') {
343             $_auto = 1, chop $_a3; $_a3 *= 1024 * 1024;
344             } elsif (lc(substr $_a3, -1, 1) eq 'k') {
345             $_auto = 1, chop $_a3; $_a3 *= 1024;
346             }
347              
348             local $/; read($_DAU_R_SOCK, $/, $_len) if $_len;
349             my ($_fh, $_buf) = ($_obj->{ $_id }); local ($!, $.);
350              
351             # support special case; e.g. $/ = "\n>" for bioinformatics
352             # anchoring ">" at the start of line
353              
354             if (!$_auto) {
355             $. = 0, $_ret = read($_fh, $_buf, $_a3);
356             }
357             elsif (!eof($_fh)) {
358             if (length $/ > 1 && substr($/, 0, 1) eq "\n") {
359             $_len = length($/) - 1;
360              
361             if (tell $_fh) {
362             $_buf = substr($/, 1);
363             $_ret = read($_fh, $_buf, $_a3, length($_buf));
364             } else {
365             $_ret = read($_fh, $_buf, $_a3);
366             }
367              
368             if (defined $_ret) {
369             $. += 1 if eof($_fh);
370             $_buf .= readline($_fh);
371              
372             substr($_buf, -$_len, $_len, '')
373             if (substr($_buf, -$_len) eq substr($/, 1));
374             }
375             }
376             elsif (defined ($_ret = read($_fh, $_buf, $_a3))) {
377             $. += 1 if eof($_fh);
378             $_buf .= readline($_fh);
379             }
380             }
381             else {
382             $_buf = '', $_ret = 0;
383             }
384              
385             if (defined $_ret) {
386             $_ret = length($_buf), $_buf = $_freeze->(\$_buf);
387             print {$_DAU_R_SOCK} "$.$LF" . length($_buf).$LF, $_buf, $_ret.$LF;
388             }
389             else {
390             print {$_DAU_R_SOCK} "$.$LF" . ( (0+$!) * -1 ).$LF;
391             }
392              
393             return;
394             },
395              
396             SHR_O_RLN.$LF => sub { # Handle READLINE
397             $_DAU_R_SOCK = ${ $_DAU_R_SOCK_REF };
398              
399             chomp($_id = <$_DAU_R_SOCK>),
400             chomp($_len = <$_DAU_R_SOCK>);
401              
402             local $/; read($_DAU_R_SOCK, $/, $_len) if $_len;
403             my ($_fh, $_buf) = ($_obj->{ $_id }); local ($!, $.);
404              
405             # support special case; e.g. $/ = "\n>" for bioinformatics
406             # anchoring ">" at the start of line
407              
408             if (length $/ > 1 && substr($/, 0, 1) eq "\n" && !eof($_fh)) {
409             $_len = length($/) - 1;
410              
411             if (tell $_fh) {
412             $_buf = substr($/, 1), $_buf .= readline($_fh);
413             } else {
414             $_buf = readline($_fh);
415             }
416              
417             substr($_buf, -$_len, $_len, '')
418             if (substr($_buf, -$_len) eq substr($/, 1));
419             }
420             else {
421             $_buf = readline($_fh);
422             }
423              
424             if (defined $_buf) {
425             $_buf = $_freeze->(\$_buf);
426             print {$_DAU_R_SOCK} "$.$LF" . length($_buf).$LF, $_buf;
427             } else {
428             print {$_DAU_R_SOCK} "$.$LF" . ( (0+$!) * -1 ).$LF;
429             }
430              
431             return;
432             },
433              
434             SHR_O_PRI.$LF => sub { # Handle PRINT
435             $_DAU_R_SOCK = ${ $_DAU_R_SOCK_REF };
436              
437             chomp($_id = <$_DAU_R_SOCK>),
438             chomp($_len = <$_DAU_R_SOCK>),
439              
440             read($_DAU_R_SOCK, my($_buf), $_len);
441             print {$_obj->{ $_id }} ${ $_thaw->($_buf) };
442              
443             return;
444             },
445              
446             SHR_O_WRI.$LF => sub { # Handle WRITE
447             $_DAU_R_SOCK = ${ $_DAU_R_SOCK_REF };
448 2     2   14 use bytes;
  2         4  
  2         7  
449              
450             chomp($_id = <$_DAU_R_SOCK>),
451             chomp($_len = <$_DAU_R_SOCK>),
452              
453             read($_DAU_R_SOCK, my($_buf), $_len);
454              
455             my $_wrote = 0;
456              
457             WRITE: {
458             $_wrote += ( syswrite (
459             $_obj->{ $_id }, $_buf, length($_buf) - $_wrote, $_wrote
460             )) or do {
461             unless ( defined $_wrote ) {
462             redo WRITE if $!{EINTR} || $!{EAGAIN} || $!{EWOULDBLOCK};
463             print {$_DAU_R_SOCK} ''.$LF;
464              
465             return;
466             }
467             };
468             }
469              
470             print {$_DAU_R_SOCK} $_wrote.$LF;
471              
472             return;
473             },
474              
475             );
476              
477             sub _init_mgr {
478 0     0   0 my $_function;
479 0         0 ( $_DAU_R_SOCK_REF, $_obj, $_function, $_freeze, $_thaw ) = @_;
480              
481 0         0 for my $key ( keys %_output_function ) {
482 0 0       0 last if exists($_function->{$key});
483 0         0 $_function->{$key} = $_output_function{$key};
484             }
485              
486 0         0 return;
487             }
488             }
489              
490             ###############################################################################
491             ## ----------------------------------------------------------------------------
492             ## Object package.
493             ##
494             ###############################################################################
495              
496             ## Items below are folded into MCE::Shared::Object.
497              
498             package # hide from rpm
499             MCE::Shared::Object;
500              
501 2     2   494 use strict;
  2         4  
  2         58  
502 2     2   11 use warnings;
  2         9  
  2         89  
503              
504 2     2   19 no warnings qw( threads recursion uninitialized numeric once );
  2         3  
  2         61  
505              
506 2     2   8 use bytes;
  2         3  
  2         7  
507              
508 2     2   64 no overloading;
  2         17  
  2         1323  
509              
510             my $_is_MSWin32 = ($^O eq 'MSWin32') ? 1 : 0;
511              
512             my ($_DAT_LOCK, $_DAT_W_SOCK, $_DAU_W_SOCK, $_dat_ex, $_dat_un, $_chn, $_obj,
513             $_freeze, $_thaw);
514              
515             sub _init_handle {
516 4     4   15 ($_DAT_LOCK, $_DAT_W_SOCK, $_DAU_W_SOCK, $_dat_ex, $_dat_un, $_chn, $_obj,
517             $_freeze, $_thaw) = @_;
518              
519 4         16 return;
520             }
521              
522             sub CLOSE {
523 9     9   1767 _req1('O~CLO', $_[0]->[0].$LF);
524             }
525              
526             sub OPEN {
527 9     9   28 my ($_id, $_fd, $_buf) = (shift()->[0]);
528 9 50       46 return unless defined $_[0];
529              
530 9 50 33     99 if (ref $_[-1] && reftype($_[-1]) ne 'GLOB') {
    50 33        
    50 33        
    50 33        
      33        
531 0         0 _croak("open error: not a GLOB reference");
532             }
533             elsif (@_ == 1 && ref $_[0] && defined($_fd = fileno($_[0]))) {
534 0         0 $_buf = $_freeze->([ "<&=$_fd" ]);
535             }
536             elsif (@_ == 2 && ref $_[1] && defined($_fd = fileno($_[1]))) {
537 0         0 $_buf = $_freeze->([ $_[0]."&=$_fd" ]);
538             }
539             elsif (!ref $_[-1]) {
540 9 50       43 $_fd = ($_[-1] =~ /&=(\d+)$/) ? $1 : -1;
541 9         123 $_buf = $_freeze->([ @_ ]);
542             }
543             else {
544 0         0 _croak("open error: unsupported use-case");
545             }
546              
547 9 50 33     35 if ($_fd > $_max_fd && !$INC{'IO/FDPass.pm'}) {
548 0         0 _croak(
549             "\nSharing a handle object while the server is running\n",
550             "requires the IO::FDPass module.\n\n"
551             );
552             }
553              
554 9 50       30 local $\ = undef if (defined $\);
555 9 50       24 local $/ = $LF if ($/ ne $LF);
556 9         33 local $MCE::Signal::SIG;
557              
558 9         13 my $_err;
559              
560             {
561 9         14 local $MCE::Signal::IPC = 1;
  9         16  
562 9 50       41 $_is_MSWin32 ? CORE::lock $_DAT_LOCK : $_dat_ex->();
563              
564 9         319 print({$_DAT_W_SOCK} 'O~OPN'.$LF . $_chn.$LF),
565 9         115 print({$_DAU_W_SOCK} $_id.$LF . $_fd.$LF . length($_buf).$LF . $_buf);
  9         116  
566 9         1031 <$_DAU_W_SOCK>;
567              
568 9 50       51 IO::FDPass::send( fileno $_DAU_W_SOCK, fileno $_fd ) if ($_fd > $_max_fd);
569 9         1461 chomp($_err = <$_DAU_W_SOCK>);
570              
571 9 50       66 $_dat_un->() if !$_is_MSWin32;
572             }
573              
574 9 50       27 CORE::kill($MCE::Signal::SIG, $$) if $MCE::Signal::SIG;
575              
576 9 50       20 if ($_err) {
577 0         0 $! = $_err;
578 0         0 '';
579             } else {
580 9         23 $! = 0;
581 9         40 1;
582             }
583             }
584              
585             sub READ {
586 7 50   7   81 local $\ = undef if (defined $\);
587 7         13 local $MCE::Signal::SIG;
588              
589 7         12 my ($_len, $_ret);
590              
591             {
592 7         8 local $MCE::Signal::IPC = 1;
  7         11  
593 7 50       28 $_is_MSWin32 ? CORE::lock $_DAT_LOCK : $_dat_ex->();
594              
595 7         226 print({$_DAT_W_SOCK} 'O~REA'.$LF . $_chn.$LF),
596 7         78 print({$_DAU_W_SOCK} $_[0]->[0].$LF . $_[2].$LF . length($/).$LF . $/);
  7         91  
597              
598 7 50       31 local $/ = $LF if ($/ ne $LF);
599 7         931 chomp($_ret = <$_DAU_W_SOCK>);
600 7         24 chomp($_len = <$_DAU_W_SOCK>);
601              
602 7 50 33     54 if ($_len && $_len > 0) {
603 7         24 read($_DAU_W_SOCK, my $_buf, $_len);
604 7         13 chomp($_len = <$_DAU_W_SOCK>);
605              
606 7         13 my $_ref = \$_[1];
607 7 100       16 if (defined $_[3]) {
608 2     2   13 no bytes;
  2         9  
  2         12  
609 1         9 substr($$_ref, $_[3], length($$_ref) - $_[3], '');
610 1         2 substr($$_ref, $_[3], $_len, ${ $_thaw->($_buf) });
  1         21  
611             }
612             else {
613 6         9 $$_ref = ${ $_thaw->($_buf) };
  6         82  
614             }
615             }
616              
617 7 50       31 $_dat_un->() if !$_is_MSWin32;
618             }
619              
620 7 50       25 CORE::kill($MCE::Signal::SIG, $$) if $MCE::Signal::SIG;
621              
622 7 100       15 if ($_len) {
623 6 50       17 if ($_len < 0) {
624 0         0 $. = 0, $! = $_len * -1;
625 0         0 return undef;
626             }
627             }
628             else {
629 1         4 my $_ref = \$_[1];
630 1 50       4 if (defined $_[3]) {
631 2     2   348 no bytes;
  2         4  
  2         12  
632 0         0 substr($$_ref, $_[3], length($$_ref) - $_[3], '');
633             }
634             else {
635 1         1 $$_ref = '';
636             }
637             }
638              
639 7         21 $. = $_ret, $! = 0;
640 7         42 $_len;
641             }
642              
643             sub READLINE {
644 29 50   29   217 local $\ = undef if (defined $\);
645 29         36 local $MCE::Signal::SIG;
646              
647 29         34 my ($_buf, $_len, $_ret);
648              
649             {
650 29         32 local $MCE::Signal::IPC = 1;
  29         34  
651 29 50       82 $_is_MSWin32 ? CORE::lock $_DAT_LOCK : $_dat_ex->();
652              
653 29         768 print({$_DAT_W_SOCK} 'O~RLN'.$LF . $_chn.$LF),
654 29         317 print({$_DAU_W_SOCK} $_[0]->[0].$LF . length($/).$LF . $/);
  29         327  
655              
656 29 50       99 local $/ = $LF if ($/ ne $LF);
657 29         2276 chomp($_ret = <$_DAU_W_SOCK>);
658 29         106 chomp($_len = <$_DAU_W_SOCK>);
659              
660 29 100 66     126 if ($_len && $_len > 0) {
661 27         63 read($_DAU_W_SOCK, $_buf, $_len);
662             }
663              
664 29 50       87 $_dat_un->() if !$_is_MSWin32;
665             }
666              
667 29 50       76 CORE::kill($MCE::Signal::SIG, $$) if $MCE::Signal::SIG;
668              
669 29 50 66     98 if ($_len && $_len < 0) {
670 0         0 $. = 0, $! = $_len * -1;
671 0         0 return undef;
672             }
673              
674 29         88 $. = $_ret, $! = 0;
675 29 100       49 $_buf ? ${ $_thaw->($_buf) } : $_buf;
  27         223  
676             }
677              
678             sub PRINT {
679 2     2   634 no bytes;
  2         4  
  2         6  
680 212     212   1352 my $_id = shift()->[0];
681 212 50       449 my $_buf = join(defined $, ? $, : "", @_);
682              
683 212 50       414 $_buf .= $\ if defined $\;
684              
685 212 50       302 if (length $_buf) {
686 212         905 $_buf = $_freeze->(\$_buf);
687 212         587 _req2('O~PRI', $_id.$LF . length($_buf).$LF, $_buf);
688             } else {
689 0         0 1;
690             }
691             }
692              
693             sub PRINTF {
694 2     2   253 no bytes;
  2         3  
  2         7  
695 10     10   95 my $_id = shift()->[0];
696 10         39 my $_buf = sprintf(shift, @_);
697              
698 10 50       22 if (length $_buf) {
699 10         52 $_buf = $_freeze->(\$_buf);
700 10         31 _req2('O~PRI', $_id.$LF . length($_buf).$LF, $_buf);
701             } else {
702 0         0 1;
703             }
704             }
705              
706             sub WRITE {
707 1     1   22 my $_id = shift()->[0];
708              
709 1 50       4 local $\ = undef if (defined $\);
710 1 50       3 local $/ = $LF if ($/ ne $LF);
711 1         3 local $MCE::Signal::SIG;
712              
713 1         2 my $_ret;
714              
715             {
716 1         1 local $MCE::Signal::IPC = 1;
  1         2  
717 1 50       4 $_is_MSWin32 ? CORE::lock $_DAT_LOCK : $_dat_ex->();
718              
719 1 50 33     27 if (@_ == 1 || (@_ == 2 && $_[1] == length($_[0]))) {
      33        
720 1         32 print({$_DAT_W_SOCK} 'O~WRI'.$LF . $_chn.$LF),
721 1         3 print({$_DAU_W_SOCK} $_id.$LF . length($_[0]).$LF, $_[0]);
  1         12  
722             }
723             else {
724 0   0     0 my $_buf = substr($_[0], ($_[2] || 0), $_[1]);
725 0         0 print({$_DAT_W_SOCK} 'O~WRI'.$LF . $_chn.$LF),
726 0         0 print({$_DAU_W_SOCK} $_id.$LF . length($_buf).$LF, $_buf);
  0         0  
727             }
728              
729 1         185 chomp($_ret = <$_DAU_W_SOCK>);
730              
731 1 50       8 $_dat_un->() if !$_is_MSWin32;
732             }
733              
734 1 50       4 CORE::kill($MCE::Signal::SIG, $$) if $MCE::Signal::SIG;
735              
736 1 50       5 (length $_ret) ? $_ret : undef;
737             }
738              
739             1;
740              
741             __END__