PageRenderTime 27ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/lifevis/site/lib/Coro/Handle.pm

http://dwarvis.googlecode.com/
Perl | 565 lines | 463 code | 95 blank | 7 comment | 54 complexity | 742210fbc2a68bb9407d4aa030479ad8 MD5 | raw file
  1. =head1 NAME
  2. Coro::Handle - non-blocking io with a blocking interface.
  3. =head1 SYNOPSIS
  4. use Coro::Handle;
  5. =head1 DESCRIPTION
  6. This module is an L<AnyEvent> user, you need to make sure that you use and
  7. run a supported event loop.
  8. This module implements IO-handles in a coroutine-compatible way, that is,
  9. other coroutines can run while reads or writes block on the handle.
  10. It does so by using L<AnyEvent|AnyEvent> to wait for readable/writable
  11. data, allowing other coroutines to run while one coroutine waits for I/O.
  12. Coro::Handle does NOT inherit from IO::Handle but uses tied objects.
  13. If at all possible, you should I<always> prefer method calls on the handle object over invoking
  14. tied methods, i.e.:
  15. $fh->print ($str); # NOT print $fh $str;
  16. my $line = $fh->readline; # NOT my $line = <$fh>;
  17. The reason is that perl recurses within the interpreter when invoking tie
  18. magic, forcing the (temporary) allocation of a (big) stack. If you have
  19. lots of socket connections and they happen to wait in e.g. <$fh>, then
  20. they would all have a costly C coroutine associated with them.
  21. =over 4
  22. =cut
  23. package Coro::Handle;
  24. no warnings;
  25. use strict;
  26. use Carp ();
  27. use Errno qw(EAGAIN EINTR EINPROGRESS);
  28. use AnyEvent::Util qw(WSAEWOULDBLOCK WSAEINPROGRESS);
  29. use base 'Exporter';
  30. our $VERSION = "5.0";
  31. our @EXPORT = qw(unblock);
  32. =item $fh = new_from_fh Coro::Handle $fhandle [, arg => value...]
  33. Create a new non-blocking io-handle using the given
  34. perl-filehandle. Returns C<undef> if no filehandle is given. The only
  35. other supported argument is "timeout", which sets a timeout for each
  36. operation.
  37. =cut
  38. sub new_from_fh {
  39. my $class = shift;
  40. my $fh = shift or return;
  41. my $self = do { local *Coro::Handle };
  42. tie $self, 'Coro::Handle::FH', fh => $fh, @_;
  43. bless \$self, ref $class ? ref $class : $class
  44. }
  45. =item $fh = unblock $fh
  46. This is a convinience function that just calls C<new_from_fh> on the
  47. given filehandle. Use it to replace a normal perl filehandle by a
  48. non-(coroutine-)blocking equivalent.
  49. =cut
  50. sub unblock($) {
  51. new_from_fh Coro::Handle $_[0]
  52. }
  53. =item $fh->writable, $fh->readable
  54. Wait until the filehandle is readable or writable (and return true) or
  55. until an error condition happens (and return false).
  56. =cut
  57. sub readable { Coro::Handle::FH::readable (tied ${$_[0]}) }
  58. sub writable { Coro::Handle::FH::writable (tied ${$_[0]}) }
  59. =item $fh->readline ([$terminator])
  60. Like the builtin of the same name, but allows you to specify the input
  61. record separator in a coroutine-safe manner (i.e. not using a global
  62. variable).
  63. =cut
  64. sub readline { tied(${+shift})->READLINE (@_) }
  65. =item $fh->autoflush ([...])
  66. Always returns true, arguments are being ignored (exists for compatibility
  67. only). Might change in the future.
  68. =cut
  69. sub autoflush { !0 }
  70. =item $fh->fileno, $fh->close, $fh->read, $fh->sysread, $fh->syswrite, $fh->print, $fh->printf
  71. Work like their function equivalents (except read, which works like
  72. sysread. You should not use the read function with Coro::Handle's, it will
  73. work but it's not efficient).
  74. =cut
  75. sub read { Coro::Handle::FH::READ (tied ${$_[0]}, $_[1], $_[2], $_[3]) }
  76. sub sysread { Coro::Handle::FH::READ (tied ${$_[0]}, $_[1], $_[2], $_[3]) }
  77. sub syswrite { Coro::Handle::FH::WRITE (tied ${$_[0]}, $_[1], $_[2], $_[3]) }
  78. sub print { Coro::Handle::FH::WRITE (tied ${+shift}, join "", @_) }
  79. sub printf { Coro::Handle::FH::PRINTF (tied ${+shift}, @_) }
  80. sub fileno { Coro::Handle::FH::FILENO (tied ${$_[0]}) }
  81. sub close { Coro::Handle::FH::CLOSE (tied ${$_[0]}) }
  82. sub blocking { !0 } # this handler always blocks the caller
  83. sub partial {
  84. my $obj = tied ${$_[0]};
  85. my $retval = $obj->[8];
  86. $obj->[8] = $_[1] if @_ > 1;
  87. $retval
  88. }
  89. =item connect, listen, bind, getsockopt, setsockopt,
  90. send, recv, peername, sockname, shutdown, peerport, peerhost
  91. Do the same thing as the perl builtins or IO::Socket methods (but return
  92. true on EINPROGRESS). Remember that these must be method calls.
  93. =cut
  94. sub connect { connect tied(${$_[0]})->[0], $_[1] or $! == EINPROGRESS or $! == WSAEINPROGRESS }
  95. sub bind { bind tied(${$_[0]})->[0], $_[1] }
  96. sub listen { listen tied(${$_[0]})->[0], $_[1] }
  97. sub getsockopt { getsockopt tied(${$_[0]})->[0], $_[1], $_[2] }
  98. sub setsockopt { setsockopt tied(${$_[0]})->[0], $_[1], $_[2], $_[3] }
  99. sub send { send tied(${$_[0]})->[0], $_[1], $_[2], @_ > 2 ? $_[3] : () }
  100. sub recv { recv tied(${$_[0]})->[0], $_[1], $_[2], @_ > 2 ? $_[3] : () }
  101. sub sockname { getsockname tied(${$_[0]})->[0] }
  102. sub peername { getpeername tied(${$_[0]})->[0] }
  103. sub shutdown { shutdown tied(${$_[0]})->[0], $_[1] }
  104. =item ($fh, $peername) = $listen_fh->accept
  105. In scalar context, returns the newly accepted socket (or undef) and in
  106. list context return the ($fh, $peername) pair (or nothing).
  107. =cut
  108. sub accept {
  109. my ($peername, $fh);
  110. while () {
  111. $peername = accept $fh, tied(${$_[0]})->[0]
  112. and return wantarray
  113. ? ($_[0]->new_from_fh($fh), $peername)
  114. : $_[0]->new_from_fh($fh);
  115. return if $! != EAGAIN && $! != EINTR && $! != WSAEWOULDBLOCK;
  116. $_[0]->readable or return;
  117. }
  118. }
  119. =item $fh->timeout ([...])
  120. The optional argument sets the new timeout (in seconds) for this
  121. handle. Returns the current (new) value.
  122. C<0> is a valid timeout, use C<undef> to disable the timeout.
  123. =cut
  124. sub timeout {
  125. my $self = tied ${$_[0]};
  126. if (@_ > 1) {
  127. $self->[2] = $_[1];
  128. $self->[5]->timeout ($_[1]) if $self->[5];
  129. $self->[6]->timeout ($_[1]) if $self->[6];
  130. }
  131. $self->[2]
  132. }
  133. =item $fh->fh
  134. Returns the "real" (non-blocking) filehandle. Use this if you want to
  135. do operations on the file handle you cannot do using the Coro::Handle
  136. interface.
  137. =item $fh->rbuf
  138. Returns the current contents of the read buffer (this is an lvalue, so you
  139. can change the read buffer if you like).
  140. You can use this function to implement your own optimized reader when neither
  141. readline nor sysread are viable candidates, like this:
  142. # first get the _real_ non-blocking filehandle
  143. # and fetch a reference to the read buffer
  144. my $nb_fh = $fh->fh;
  145. my $buf = \$fh->rbuf;
  146. while () {
  147. # now use buffer contents, modifying
  148. # if necessary to reflect the removed data
  149. last if $$buf ne ""; # we have leftover data
  150. # read another buffer full of data
  151. $fh->readable or die "end of file";
  152. sysread $nb_fh, $$buf, 8192;
  153. }
  154. =cut
  155. sub fh {
  156. (tied ${$_[0]})->[0];
  157. }
  158. sub rbuf : lvalue {
  159. (tied ${$_[0]})->[3];
  160. }
  161. sub DESTROY {
  162. # nop
  163. }
  164. our $AUTOLOAD;
  165. sub AUTOLOAD {
  166. my $self = tied ${$_[0]};
  167. (my $func = $AUTOLOAD) =~ s/^(.*):://;
  168. my $forward = UNIVERSAL::can $self->[7], $func;
  169. $forward or
  170. die "Can't locate object method \"$func\" via package \"" . (ref $self) . "\"";
  171. goto &$forward;
  172. }
  173. package Coro::Handle::FH;
  174. no warnings;
  175. use strict;
  176. use Carp 'croak';
  177. use Errno qw(EAGAIN EINTR);
  178. use AnyEvent ();
  179. use AnyEvent::Util qw(WSAEWOULDBLOCK);
  180. # formerly a hash, but we are speed-critical, so try
  181. # to be faster even if it hurts.
  182. #
  183. # 0 FH
  184. # 1 desc
  185. # 2 timeout
  186. # 3 rb
  187. # 4 wb # unused
  188. # 5 read watcher, if Coro::Event used
  189. # 6 write watcher, if Coro::Event used
  190. # 7 forward class
  191. # 8 blocking
  192. sub TIEHANDLE {
  193. my ($class, %arg) = @_;
  194. my $self = bless [], $class;
  195. $self->[0] = $arg{fh};
  196. $self->[1] = $arg{desc};
  197. $self->[2] = $arg{timeout};
  198. $self->[3] = "";
  199. $self->[4] = "";
  200. $self->[7] = $arg{forward_class};
  201. $self->[8] = $arg{partial};
  202. AnyEvent::Util::fh_nonblocking $self->[0], 1;
  203. $self
  204. }
  205. sub cleanup {
  206. $_[0][5]->cancel if $_[0][5];
  207. $_[0][6]->cancel if $_[0][6];
  208. @{$_[0]} = ();
  209. }
  210. sub OPEN {
  211. &cleanup;
  212. my $self = shift;
  213. my $r = @_ == 2 ? open $self->[0], $_[0], $_[1]
  214. : open $self->[0], $_[0], $_[1], $_[2];
  215. if ($r) {
  216. fcntl $self->[0], &Fcntl::F_SETFL, &Fcntl::O_NONBLOCK
  217. or croak "fcntl(O_NONBLOCK): $!";
  218. }
  219. $r
  220. }
  221. sub PRINT {
  222. WRITE (shift, join "", @_)
  223. }
  224. sub PRINTF {
  225. WRITE (shift, sprintf shift, @_)
  226. }
  227. sub GETC {
  228. my $buf;
  229. READ ($_[0], $buf, 1);
  230. $buf
  231. }
  232. sub BINMODE {
  233. binmode $_[0][0];
  234. }
  235. sub TELL {
  236. Carp::croak "Coro::Handle's don't support tell()";
  237. }
  238. sub SEEK {
  239. Carp::croak "Coro::Handle's don't support seek()";
  240. }
  241. sub EOF {
  242. Carp::croak "Coro::Handle's don't support eof()";
  243. }
  244. sub CLOSE {
  245. &cleanup;
  246. close $_[0][0]
  247. }
  248. sub DESTROY {
  249. &cleanup;
  250. }
  251. sub FILENO {
  252. fileno $_[0][0]
  253. }
  254. # seems to be called for stringification (how weird), at least
  255. # when DumpValue::dumpValue is used to print this.
  256. sub FETCH {
  257. "$_[0]<$_[0][1]>"
  258. }
  259. sub readable_anyevent {
  260. my $current = $Coro::current;
  261. my $io = 1;
  262. my $w = AnyEvent->io (
  263. fh => $_[0][0],
  264. poll => 'r',
  265. cb => sub {
  266. $current->ready if $current;
  267. undef $current;
  268. },
  269. );
  270. my $t = (defined $_[0][2]) && AnyEvent->timer (
  271. after => $_[0][2],
  272. cb => sub {
  273. $io = 0;
  274. $current->ready if $current;
  275. undef $current;
  276. },
  277. );
  278. &Coro::schedule;
  279. &Coro::schedule while $current;
  280. $io
  281. }
  282. sub writable_anyevent {
  283. my $current = $Coro::current;
  284. my $io = 1;
  285. my $w = AnyEvent->io (
  286. fh => $_[0][0],
  287. poll => 'w',
  288. cb => sub {
  289. $current->ready if $current;
  290. undef $current;
  291. },
  292. );
  293. my $t = (defined $_[0][2]) && AnyEvent->timer (
  294. after => $_[0][2],
  295. cb => sub {
  296. $io = 0;
  297. $current->ready if $current;
  298. undef $current;
  299. },
  300. );
  301. &Coro::schedule while $current;
  302. $io
  303. }
  304. sub readable_coro {
  305. ($_[0][5] ||= "Coro::Event"->io (
  306. fd => $_[0][0],
  307. desc => "fh $_[0][1] read watcher",
  308. timeout => $_[0][2],
  309. poll => &Event::Watcher::R + &Event::Watcher::E + &Event::Watcher::T,
  310. ))->next->[4] & &Event::Watcher::R
  311. }
  312. sub writable_coro {
  313. ($_[0][6] ||= "Coro::Event"->io (
  314. fd => $_[0][0],
  315. desc => "fh $_[0][1] write watcher",
  316. timeout => $_[0][2],
  317. poll => &Event::Watcher::W + &Event::Watcher::E + &Event::Watcher::T,
  318. ))->next->[4] & &Event::Watcher::W
  319. }
  320. #sub readable_ev {
  321. # &EV::READ == Coro::EV::timed_io_once (fileno $_[0][0], &EV::READ , $_[0][2])
  322. #}
  323. #
  324. #sub writable_ev {
  325. # &EV::WRITE == Coro::EV::timed_io_once (fileno $_[0][0], &EV::WRITE, $_[0][2])
  326. #}
  327. # decide on event model at runtime
  328. for my $rw (qw(readable writable)) {
  329. no strict 'refs';
  330. *$rw = sub {
  331. AnyEvent::detect;
  332. if ($AnyEvent::MODEL eq "AnyEvent::Impl::Coro" or $AnyEvent::MODEL eq "AnyEvent::Impl::Event") {
  333. require Coro::Event;
  334. *$rw = \&{"$rw\_coro"};
  335. } elsif ($AnyEvent::MODEL eq "AnyEvent::Impl::CoroEV" or $AnyEvent::MODEL eq "AnyEvent::Impl::EV") {
  336. require Coro::EV;
  337. *$rw = \&{"Coro::EV::$rw\_ev"};
  338. return &$rw; # Coro 5.0+ doesn't support goto &SLF
  339. } else {
  340. *$rw = \&{"$rw\_anyevent"};
  341. }
  342. goto &$rw
  343. };
  344. };
  345. sub WRITE {
  346. my $len = defined $_[2] ? $_[2] : length $_[1];
  347. my $ofs = $_[3];
  348. my $res = 0;
  349. while () {
  350. my $r = syswrite ($_[0][0], $_[1], $len, $ofs);
  351. if (defined $r) {
  352. $len -= $r;
  353. $ofs += $r;
  354. $res += $r;
  355. last unless $len;
  356. } elsif ($! != EAGAIN && $! != EINTR && $! != WSAEWOULDBLOCK) {
  357. last;
  358. }
  359. last unless &writable;
  360. }
  361. return $res;
  362. }
  363. sub READ {
  364. my $len = $_[2];
  365. my $ofs = $_[3];
  366. my $res = 0;
  367. # first deplete the read buffer
  368. if (length $_[0][3]) {
  369. my $l = length $_[0][3];
  370. if ($l <= $len) {
  371. substr ($_[1], $ofs) = $_[0][3]; $_[0][3] = "";
  372. $len -= $l;
  373. $ofs += $l;
  374. $res += $l;
  375. return $res unless $len;
  376. } else {
  377. substr ($_[1], $ofs) = substr ($_[0][3], 0, $len);
  378. substr ($_[0][3], 0, $len) = "";
  379. return $len;
  380. }
  381. }
  382. while() {
  383. my $r = sysread $_[0][0], $_[1], $len, $ofs;
  384. if (defined $r) {
  385. $len -= $r;
  386. $ofs += $r;
  387. $res += $r;
  388. last unless $len && $r;
  389. } elsif ($! != EAGAIN && $! != EINTR && $! != WSAEWOULDBLOCK) {
  390. last;
  391. }
  392. last if $_[0][8] || !&readable;
  393. }
  394. return $res;
  395. }
  396. sub READLINE {
  397. my $irs = @_ > 1 ? $_[1] : $/;
  398. my ($ofs, $len);
  399. while() {
  400. if (defined $irs) {
  401. my $pos = index $_[0][3], $irs, $ofs < 0 ? 0 : $ofs;
  402. if ($pos >= 0) {
  403. $pos += length $irs;
  404. my $res = substr $_[0][3], 0, $pos;
  405. substr ($_[0][3], 0, $pos) = "";
  406. return $res;
  407. }
  408. $ofs = (length $_[0][3]) - (length $irs);
  409. }
  410. $len = sysread $_[0][0], $_[0][3], $len + 4096, length $_[0][3];
  411. if (defined $len) {
  412. return length $_[0][3] ? delete $_[0][3] : undef
  413. unless $len;
  414. } elsif (($! != EAGAIN && $! != EINTR && $! != WSAEWOULDBLOCK) || !&readable) {
  415. return length $_[0][3] ? delete $_[0][3] : undef;
  416. }
  417. }
  418. }
  419. 1;
  420. =back
  421. =head1 BUGS
  422. - Perl's IO-Handle model is THE bug.
  423. =head1 AUTHOR
  424. Marc Lehmann <schmorp@schmorp.de>
  425. http://home.schmorp.de/
  426. =cut