1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785
|
@node I/O system
@section I/O system
Scheme48 supports a sophisticated, non-blocking, user-extensible I/O
system untied to any particular operating system's I/O facilities. It
is based in three levels: channels, ports, and the facilities already
built with both ports and channels in Scheme48, such as buffering.
@menu
* Ports:: Abstract & generalized I/O objects.
* Programmatic ports:: Designing custom ports.
* Miscellaneous I/O internals:: Various internal I/O system routines.
* Channels:: Low-level interface to OS facilities.
* Channel ports:: Ports built upon channels.
@end menu
@node Ports
@subsection Ports
While channels provide the low-level interface directly to the OS's I/O
facilities, @dfn{ports} provide a more abstract & generalized mechanism
for I/O transmission. Rather than being specific to channels or being
themselves primitive I/O devices, ports are functionally parameterized.
This section describes the usual I/O operations on ports. The next
section describes the programmatic port parameterization mechanism, and
the section following that describes the most commonly used built-in
port abstraction, ports atop channels.
@subsubsection Port operations
@stindex i/o
The following names are exported by the @code{i/o} structure.
@deffn procedure input-port? value @returns{} boolean
@deffnx procedure output-port? value @returns{} boolean
These return @code{#t} if their argument is both a port and either an
input port or output port, respectively, or @code{#f} if neither
condition is true.
@end deffn
@deffn procedure close-input-port port @returns{} unspecified
@deffnx procedure close-output-port port @returns{} unspecified
Closes @var{port}, which must be an input port or an output port,
respectively.
@end deffn
@deffn procedure char-ready? [port] @returns{} boolean
@deffnx procedure output-port-ready? port @returns{} boolean
@code{Char-ready?} returns a true value if there is a character ready
to be read from @var{port} and @code{#f} if there is no character
ready. @var{Port} defaults to the current input port if absent; see
below on current ports. @code{Output-port-ready?} returns a true value
if @var{port} is ready to receive a single written character and
@code{#f} if not.
@end deffn
@cindex block input and output
@cindex input and output of blocks
@deffn procedure read-block block start count port [wait?] @returns{} count-read or EOF
@deffnx procedure write-block block start count port @returns{} count-written
@deffnx procedure write-string string port @returns{} char-count-written
@code{Read-block} attempts to read @var{count} elements from @var{port}
into @var{block}, which may be a string or a byte vector, starting at
@var{start}. If fewer than @var{count} characters or bytes are
available to read from @var{port}, and @var{wait?} is a true value or
absent, @code{read-block} will wait until @var{count} characters are
available and read into @var{block}; if @var{wait?} is @code{#f},
@code{read-block} immediately returns. @code{Read-block} returns the
number of elements read into @var{block}, or an end of file object if
the stream's end is immediately encountered. @code{Write-block} writes
@var{count} elements from @var{block}, which may be a string or a byte
vector, starting at @var{start} to @var{port}. @code{Write-string} is
a convenience atop @code{write-block} for writing the entirety of a
string to a port.
@end deffn
@deffn procedure newline [port] @returns{} unspecified
Writes a newline character or character sequence to the output port
@var{port}. @var{Port} defaults to the current output port; see below
on current ports.
@end deffn
@deffn procedure disclose-port port @returns{} disclosed
Returns a disclosed representation of @var{port}; @pxref{Writer}.
@end deffn
@cindex forcing buffered output
@cindex output port buffer forcing
@cindex buffered output forcing
@cindex flushing output buffers
@deffn procedure force-output port @returns{} unspecified
Forces all buffered output in the output port @var{port} to be sent.
@end deffn
@deffn procedure make-null-output-port @returns{} output-port
Returns an output port that will ignore any output it receives.
@end deffn
@subsubsection Current ports
Scheme48 keeps in its @embedref{Fluid/dynamic bindings, dynamic
environment} a set of `current' ports. These include R5RS's current
input and output ports, as well as ports for general noise produced by
the system, and ports for where error messages are printed. These
procedures are exported by the @code{i/o} structure.
@deffn procedure current-input-port @returns{} input-port
@deffnx procedure current-output-port @returns{} output-port
@deffnx procedure current-noise-port @returns{} output-port
@deffnx procedure current-error-port @returns{} output-port
These return the values in the current dynamic environment of the
respective ports. @code{Current-input-port} and
@code{current-output-port} are also exported by the @code{scheme}
structure.
@end deffn
@deffn procedure input-port-option arguments @returns{} input-port
@deffnx procedure output-port-option arguments @returns{} output-port
These are utilities for retrieving optional input and output port
arguments from rest argument lists, defaulting to the current input or
output ports. For example, assuming the newline character sequence is
simply @code{#\newline}, @code{newline} might be written as:
@lisp
(define (newline . maybe-port)
(write-char #\newline (output-port-option maybe-port)))@end lisp
@end deffn
@cindex noise output
@deffn procedure silently thunk @returns{} values
This stifles output from the current noise port in the dynamic extent
of @var{thunk}, which is applied to zero arguments. @code{Silently}
returns the values that @var{thunk} returns.
@end deffn
@deffn procedure with-current-ports input output error thunk @returns{} values
@code{With-current-ports} dynamically binds the current input, output,
and error ports to @var{input}, @var{output}, and @var{error},
respectively, in the dynamic extent of @var{thunk}, which is applied
to zero arguments. The current noise port is also bound to
@var{error}. @code{With-current-ports} returns the values that
@var{thunk} returns.
@end deffn
@stindex i/o-internal
Similarly to @code{with-current-ports}, the @code{i/o-internal}
structure also exports these procedures:
@deffn procedure call-with-current-input-port port thunk @returns{} values
@deffnx procedure call-with-current-output-port port thunk @returns{} values
@deffnx procedure call-with-current-noise-port port thunk @returns{} values
These bind individual current ports for the dynamic extent of each
@var{thunk}, which is applied to zero arguments. These all return the
values that @var{thunk} returns.
@end deffn
@node Programmatic ports
@subsection Programmatic ports
Ports are user-extensible; all primitive port operations on them ---
@code{read-char}, @code{write-block}, @etc{} --- are completely
generalized. Abstractions for buffered ports are also available.
@menu
* Port data type::
* Port handlers::
* Buffered ports & handlers::
@end menu
@node Port data type
@subsubsection Port data type
@stindex ports
The @code{ports} structure defines the basis of the port data type and
exports the following procedures.
@deffn procedure make-port handler status lock data buffer index limit pending-eof? @returns{} port
Port constructor. The arguments are all the fields of ports, which are
described below. Note that @code{make-port} is rarely called directly;
usually one will use one of the buffered port constructors instead.
@end deffn
@deffn procedure port-handler port @returns{} port-handler
@deffnx procedure port-buffer port @returns{} buffer or @code{#f}
@deffnx procedure port-lock port @returns{} value
@deffnx procedure port-status port @returns{} integer-status
@deffnx procedure port-data port @returns{} value
@deffnx procedure port-index port @returns{} integer or @code{#f}
@deffnx procedure port-limit port @returns{} integer or @code{#f}
@deffnx procedure port-pending-eof? port @returns{} boolean
Accessors for the port fields:
@table @code
@item handler
The handler is the functional parameterization mechanism: it provides
all the port's operations, such as reading/writing blocks, disclosing
(@pxref{Writer}) the port, closing the port, @etcT{}.
@xref{Port handlers}.
@item buffer
The buffer is used for buffered ports, where it is a @embedref{Bitwise
manipulation, byte vector}. It may be any value for unbuffered ports.
@item lock
This misnamed field was originally used for a mutual exclusion lock,
before optimistic concurrency was made the native synchronization
mechanism in Scheme48. It is now used as a `timestamp' for buffered
ports: it is provisionally written to with a unique value when a thread
resets the @code{index} to reuse the buffer, and it is provisionally
read from when reading from the buffer. In this way, if the buffer is
reset while another thread is reading from it, the other thread's
proposal is invalidated by the different value in memory than what was
there when it logged the old timestamp in its proposal.
@item status
A mask from the @code{port-status-options} enumeration;
@pxref{Miscellaneous I/O internals}.
@c @xref{Architecture}.
@item data
Arbitrary data for particular kinds of ports. For example, for a port
that tracks line & column information (@pxref{I/O extensions}), this
might be a record containing the underlying port, the line number, and
the column number.
@item index
The current index into a buffered port's buffer. If the port is not
buffered, this is @code{#f}.
@item limit
The limit of the @code{index} field for a buffered port's buffer. When
the @code{index} field is equal to the @code{limit} field, the buffer
is full. If the port is not buffered, this is @code{#f}.
@item pending-eof?
For output ports, this is a boolean flag indicating whether the buffer
has been forced to output recently. For input ports, this is a boolean
flag indicating whether an end of file is pending after reading through
the current buffer.
@end table
@end deffn
@deffn procedure set-port-lock! port value @returns{} unspecified
@deffnx procedure set-port-status! port status @returns{} unspecified
@deffnx procedure set-port-data! port data @returns{} unspecified
@deffnx procedure set-port-index! port index @returns{} unspecified
@deffnx procedure set-port-limit! port index @returns{} unspecified
@deffnx procedure set-port-pending-eof?! port pending-eof? @returns{} unspecified
These assign respective fields of ports. The @code{buffer} and
@code{handler} fields, however, are immutable.
@end deffn
@cindex logging operations
@cindex optimistic concurrency logging operations
@deffn procedure provisional-port-handler port @returns{} port-handler
@deffnx procedure provisional-port-lock port @returns{} value
@deffnx procedure provisional-port-status port @returns{} integer-status
@deffnx procedure provisional-port-data port @returns{} value
@deffnx procedure provisional-port-index port @returns{} integer or @code{#f}
@deffnx procedure provisional-port-limit port @returns{} integer or @code{#f}
@deffnx procedure provisional-port-pending-eof? port @returns{} boolean
@deffnx procedure provisional-set-port-lock! port value @returns{} unspecified
@deffnx procedure provisional-set-port-status! port status @returns{} unspecified
@deffnx procedure provisional-set-port-data! port data @returns{} unspecified
@deffnx procedure provisional-set-port-index! port index @returns{} unspecified
@deffnx procedure provisional-set-port-limit! port index @returns{} unspecified
@deffnx procedure provisional-set-port-pending-eof?! port pending-eof? @returns{} unspecified
Provisional versions of the above port accessors & modifiers; that is,
accessors & modifiers that log in the current proposal, if there is
one.
@end deffn
@node Port handlers
@subsubsection Port handlers
@stindex i/o-internal
@dfn{Port handlers} store a port's specific operations for the general
port operations, such as block reads and writes, buffer flushing,
@etcT{}. Port handler constructors, including @code{make-port-handler}
& the buffered port handlers in the next section, are available from
the @code{i/o-internal} structure.
@deffn procedure make-port-handler discloser closer char-reader/writer block-reader/writer readiness-tester buffer-forcer @returns{} port-handler
Basic port handler constructor. The arguments are used for the port
handler fields. Each field contains a procedure. The expected
semantics of each procedure depend on whether the port is for input or
output. Input ports do not use the @code{buffer-forcer} field. The
first two fields are independent of the type of port:
@table @asis
@item @tabledfn{discloser, port, disclosed}
Returns a disclosed representation of the port, @ie{} a list whose
@code{car} is the `type name' of this handler (usually with a suffix of
either @code{-input-port} or @code{-output-port}) followed by a list of
all of the components to be printed; @pxref{Writer}.
@item @tabledfn{closer, port, ignored}
Closes @var{port}. This operation corresponds with the
@code{close-input-port} & @code{close-output-port} procedures.
@end table
For input ports, the remaining fields are:
@table @asis
@item @tabledfn{char-reader, port consume?, char}
Reads a single character from @var{port}. If @var{consume?} is true,
the character should be consumed from @var{port}; if @var{consume?} is
@code{#f}, however, the character should be left in @var{port}'s input
stream. If @var{consume?} is true, this operation corresponds with
@code{read-char}; if it is @code{#f}, this operation corresponds with
@code{peek-char}.
@item @tabledfn{block-reader, port block start count wait?, count-written or EOF}
Attempts to read @var{count} characters from @var{port}'s input stream
into the string or byte vector @var{block}, starting at @var{start}.
In the case that an insufficient number of characters is available, if
@var{wait?} is true, the procedure should wait until all of the wanted
characters are available; otherwise, if @var{wait?} is @code{#f}, the
block reader should immediately return. In either case, it returns the
number of characters that were read into @var{block}, or an end of file
object if it immediately reached the end of the stream. Buffered ports
will typically just copy elements from the buffer into @var{block},
rather than reading from any internal I/O channel in @var{port}. This
operation corresponds with @code{read-block}.
@item @tabledfn{readiness-tester, port, boolean}
Returns a true value if there is a character available to be read in
@var{port} or @code{#f} if not. This operation corresponds with the
@code{char-ready?} procedure.
@end table
For output ports, the remaining fields are:
@table @asis
@item @tabledfn{char-writer, port char, ignored}
Writes the single character @var{char} to @var{port}. This operation
corresponds with @code{write-char}.
@item @tabledfn{block-writer, port block start count, count-written}
Writes @var{count} characters to @var{port} from @var{block}, starting
at @var{start}. @var{Block} may be a string or a byte vector. This
will usually involve copying contents of @var{block} to @var{port}'s
buffer, if it is buffered. This operation corresponds with
@code{write-block}.
@item @tabledfn{readiness-tester, port, boolean}
Returns a true value if @var{port} is ready to receive a character and
@code{#f} if not.
@item @tabledfn{buffer-forcer, port necessary?, ignored}
For buffered ports, this is intended to force all buffered output to
the actual internal I/O channel of @var{port}. @var{Necessary?} tells
whether or not it is absolutely necessary to force all the output
immediately; if it is @code{#t}, the buffer forcer is required to force
all output in the buffer before it returns. If @var{necessary?} is
@code{#f}, not only may it just register an I/O transaction without
waiting for it to complete, but it also should @emph{not} signal an
error if @var{port} is already closed. For unbuffered ports, this
operation need not do anything at all.
@end table
@end deffn
@node Buffered ports & handlers
@subsubsection Buffered ports & handlers
@cindex buffered input and output
@stindex i/o-internal
Along with bare port handlers, Scheme48 provides conveniences for many
patterns of buffered ports & port handlers. These names are exported
by the @code{i/o-internal} structure. Buffered ports are integrated
with Scheme48's @embedref{Optimistic concurrency, optimistic
concurrency} facilities.
@strong{Note:} Although internally buffered ports are integrated with
optimistic concurrency, operations on buffered ports, like operations
on channels, cannot be reliably fusibly atomic.
@deffn procedure make-buffered-input-port handler data buffer index limit @returns{} input-port
@deffnx procedure make-buffered-output-port handler data buffer index limit @returns{} output-port
Constructors for buffered ports. @var{Handler} is the port's handler,
which is usually constructed with one of the buffered port handler
constructors (see below). @var{Data} is arbitrary data to go in the
port's @code{data} field. @var{Buffer} is a byte vector whose length
is greater than or equal to both @var{index} & @var{limit}.
@var{Index} is the initial index into @var{buffer} to go in the port's
@code{index} field. @var{Limit} is the limit in the port's buffer, to
go into the port's @code{limit} field; nothing will be written into
@var{buffer} at or past @var{limit}.
@end deffn
@deffn procedure make-unbuffered-input-port handler data @returns{} input-port
@deffnx procedure make-unbuffered-output-port handler data @returns{} output-port
Conveniences for ports that are explicitly @emph{not} buffered. Only
the relevant fields are passed; all fields pertaining to buffering are
initialized with @code{#f}.
@end deffn
@deffn procedure make-buffered-input-port-handler discloser closer buffer-filler readiness-tester @returns{} port-handler
This creates a port handler for buffered input ports. The arguments
are as follows:
@table @asis
@item @tabledfn{discloser, port-data, disclosed}
@itemx @tabledfn{closer, port-data, ignored}
@var{Discloser} & @var{closer} are like the similarly named regular
port handler fields, but they are applied directly to the port's data,
not to the port itself.
@item @tabledfn{buffer-filler, port wait?, committed?}
Used to fill @var{port}'s buffer when it no longer has contents from
which to read in its current buffer. @var{Wait?} is a boolean flag,
@code{#t} if the operation should wait until the I/O transaction
necessary to fill the buffer completes, or @code{#f} if it may simply
initiate an I/O transaction but not wait until it completes (@eg{}, use
@code{channel-maybe-commit-and-read}, but not wait on the condition
variable passed to @code{channel-maybe-commit-and-read}).
@var{Buffer-filler} is called with a fresh proposal in place, and it is
the responsibility of @var{buffer-filler} to commit it. It returns a
boolean flag denoting whether the proposal was committed. The last call
in @var{buffer-filler} is usually either @code{(maybe-commit)} or a
call to a procedure that causes that effect (@eg{}, one of the
operation on condition variables that commits the current proposal.
@xref{Higher-level synchronization, condition variables}.)
@item @tabledfn{readiness-tester, port, [committed? ready?]}
Called when @code{char-ready?} is applied to @var{port} and the buffer
of @var{port} is empty. Like @var{buffer-filler},
@var{readiness-tester} is applied with a fresh proposal in place, which
it should attempt to commit. @var{Readiness-tester} should return two
values, each a boolean flag: the first denotes whether or not the
current proposal was successfully committed, and, if it was successful,
whether or not a character is ready.
@end table
@end deffn
@deffn procedure make-buffered-output-port-handler discloser buffer-emptier readiness-tester @returns{} port-handler
This creates a port handler for buffered output ports. @var{Discloser}
& @var{closer} are as with buffered input ports. The remaining fields
are as follows:
@table @asis
@item @tabledfn{buffer-emptier, port necessary?, committed?}
@var{Buffer-emptier} is used when @var{port}'s buffer is full and needs
to be emptied. It is called with a fresh proposal in place. It should
reset @var{port}'s @code{index} field, call @code{note-buffer-reuse!}
to invalidate other threads' transactions on the recycled buffer, and
attempt to commit the new proposal installed. It returns a boolean
flag indicating whether or not the commit succeeded.
@item @tabledfn{readiness-tester, port, [committed? ready?]}
@var{Readiness-tester} is applied to @var{port} when its buffer is full
(@ie{} its @code{index} & @code{limit} fields are equal) and
@code{output-port-ready?} is applied to @var{port}. After performing
the test, it should attempt to commit the current proposal and then
return two values: whether it succeeded in committing the current
proposal, and, if it was successful, whether or not a character is
ready to be outputted.
@end table
@end deffn
@defvr constant default-buffer-size @returns{} integer
The default size for port buffers. This happens to be 4096 in the
current version of Scheme48.
@end defvr
@deffn procedure note-buffer-reuse! port @returns{} unspecified
@deffnx procedure check-buffer-timestamp! port @returns{} unspecified
These are used to signal the resetting of a buffer between multiple
threads. @code{Note-buffer-reuse!} is called --- in the case of an
output port --- when a buffer fills up, is emptied, and flushed; or ---
in the case of an input port --- when a buffer is emptied and needs to
be refilled. @code{Note-buffer-reuse!} logs in the current proposal a
fresh value to store in @var{port}. When that proposal is committed,
this fresh value is stored in the port. Other threads that were using
@var{port}'s buffer call @code{check-buffer-timestamp!}, which logs a
read in the current proposal. If another thread commits a buffer reuse
to memory, that read will be invalidated, invalidating the whole
transaction.
@end deffn
@node Miscellaneous I/O internals
@subsection Miscellaneous I/O internals
@stindex i/o-internal
@stindex architecture
All of these but @code{port-status-options} are exported by the
@code{i/o-internal} structure; the @code{port-status-options}
enumeration is exported by the @code{architecture} structure, but it
deserves mention in this section.
@defvr {enumeration} port-status-options
@lisp
(define-enumeration port-status-options
(input
output
open-for-input
open-for-output))@end lisp
Enumeration of indices into a port's @code{status} field bit set.
@end defvr
@deffn procedure open-input-port? port @returns{} boolean
@deffnx procedure open-output-port? port @returns{} boolean
These return true values if @var{port} is both an input or output port,
respectively, and open.
@end deffn
@defvr constant open-input-port-status @returns{} integer-status
@defvrx constant open-output-port-status @returns{} integer-status
The bitwise masks of enumerands from the @code{port-status-options}
enumeration signifying an open input or output port, respectively.
@end defvr
@deffn procedure make-input-port-closed! port @returns{} unspecified
@deffnx procedure make-output-port-closed! port @returns{} unspecified
These set the status of @var{port}, which must be an input or output
port, respectively, to indicate that it is closed.
@end deffn
@deffn procedure eof-object @returns{} eof-object
Returns the EOF object token. This is the only value that will answer
true to R5RS's @code{eof-object?} predicate.
@end deffn
@deffn procedure force-output-if-open port @returns{} unspecified
This forces @var{port}'s output if it is an open output port, and does
not block.
@end deffn
@deffn procedure periodically-force-output! port @returns{} unspecified
@deffnx procedure periodically-flushed-ports @returns{} port-list
@code{Periodically-force-output!} registers @var{port} to be forced
periodically. Only a weak reference to @var{port} in this registry is
held, however, so this cannot cause accidental space leaks.
@code{Periodically-flushed-ports} returns a list of all ports in this
registry. Note that the returned list holds strong references to all
of its elements. @code{Periodically-flushed-ports} does not permit
thread context switches, or interrupts of any sort, while it runs.
@end deffn
@node Channels
@subsection Channels
@cindex channels
@dfn{Channels} represent the OS's native I/O transmission channels. On
Unix, channels are essentially boxed file descriptors, for example.
The only operations on channels are block reads & writes. Blocks in
this sense may be either strings or @embedref{Bitwise manipulation,
byte vectors}.
@subsubsection Low-level channel operations
@stindex channels
The low-level base of the interface to channels described here is
exported from the @code{channels} structure.
@deffn procedure channel? @returns{} boolean
Disjoint type predicate for channels.
@end deffn
@deffn procedure channel-id channel @returns{} value
@deffnx procedure channel-status channel @returns{} integer-enumerand
@deffnx procedure channel-os-index channel @returns{} integer
@code{Channel-id} returns @var{channel}'s id. The id is some
identifying characteristic of channels. For example, file channels'
ids are usually the corresponding filenames; channels such as the
standard input, output, or error output channels have names like
@code{"standard input"} and @code{"standard output"}.
@code{Channel-status} returns the current status of @var{channel}; see
the @code{channel-status-option} enumeration below.
@code{Channel-os-index} returns the OS-specific integer index of
@var{channel}. On Unix, for example, this is the channel's file
descriptor.
@end deffn
@cindex file channels
@deffn procedure open-channel filename option close-silently? @returns{} channel
@code{Open-channel} opens a channel for a file given its filename.
@var{Option} specifies what type of channel this is; see the
@code{channel-status-option} enumeration below. @var{Close-silently?}
is a boolean that specifies whether a message should be printed (on
Unix, to @code{stderr}) when the resulting channel is closed after a
garbage collector finds it unreachable.
@end deffn
@cindex closing channels
@deffn procedure close-channel channel @returns{} unspecified
Closes @var{channel} after aborting any potential pending I/O
transactions it may have been involved with.
@end deffn
@deffn procedure channel-ready? channel @returns{} boolean
If @var{channel} is an input channel: returns @code{#t} if there is
input ready to be read from @var{channel} or @code{#f} if not; if
@var{channel} is an output channel: returns @code{#t} if a write would
immediately take place upon calling @code{channel-maybe-write}, @ie{}
@code{channel-maybe-write} would not return @code{#f}, or @code{#f} if
not.
@end deffn
@deffn procedure channel-maybe-read channel buffer start-index octet-count wait? @returns{} octet count read, error status cell, EOF object, or @code{#f}
@deffnx procedure channel-maybe-write channel buffer start-index octet-count @returns{} octet count written, error status cell, or @code{#f}
@deffnx procedure channel-abort channel @returns{} unspecified
@code{Channel-maybe-read} attempts to read @var{octet-count} octets
from @var{channel} into @var{buffer}, starting at @var{start-index}.
If a low-level I/O error occurs, it returns a cell containing a token
given by the operating system indicating what kind of error occurred.
If @var{wait?} is @code{#t}, and @var{channel} is not ready to be read
from, @var{channel} is registered for the VM's event polling mechanism,
and @code{channel-maybe-read} returns @code{#f}. Otherwise, it returns
either the number of octets read, or an EOF object if @var{channel} was
was at the end.
@code{Channel-maybe-write} attempts to write @var{octet-count} octets
to @var{channel} from @var{buffer}, starting at @var{start-index}. If
a low-level I/O error occurs, it returns a cell indicating a token
given by the operating system indicating what kind of error occurred.
If no such low-level error occurs, it registers @var{channel} for the
VM's event polling mechanism and returns @code{#f} iff zero octets were
immediately written or the number of octets immediately written if any
were.
@code{Channel-abort} aborts any pending operation registered for the
VM's event polling mechanism.
@end deffn
@deffn procedure open-channels-list @returns{} channel-list
Returns a list of all open channels in order of the @code{os-index}
field.
@end deffn
@defvr {enumeration} channel-status-option
@lisp
(define-enumeration channel-status-option
(closed
input
output
special-input
special-output))@end lisp
Enumeration for a channel's status. The @code{closed} enumerand is
used only after a channel has been closed. Note that this is
@emph{not} suitable for a bit mask; that is, one may choose exactly
one of the enumerands, not use a bit mask of status options. For
example, to open a file @file{frob} for input that one wishes the
garbage collector to be silent about on closing it:
@lisp
(open-channel "frob"
(enum channel-status-option input)
#t)
@result{} #@{Input-channel "frob"@}@end lisp
@end defvr
@subsubsection Higher-level channel operations
@cindex channel utilities, higher-level
@cindex higher-level channel utilities
@stindex channel-i/o
More convenient abstractions for operating on channels, based on
@embedref{Higher-level synchronization, condition variables}, are
provided from the @code{channel-i/o} structure. They are integrated
with Scheme48's @embedref{Optimistic concurrency, optimistic
concurrency} facilities.
@strong{Note:} Transactions on channels can @emph{not} be atomic in the
sense of optimistic concurrency. Since they involve communication with
the outside world, they are irrevocable transactions, and thus an
invalidated proposal cannot retract the transaction on the channel.
@c What long names you have, my dear!
@deffn procedure channel-maybe-commit-and-read channel buffer start-index octet-count condvar wait? @returns{} committed?
@deffnx procedure channel-maybe-commit-and-write channel buffer start-index octet-count condvar @returns{} committed?
These attempt to commit the current proposal. If they fail, they
immediately return @code{#f}; otherwise, they proceed, and return
@code{#t}. If the commit succeeded, these procedures attempt an I/O
transaction, without blocking. @code{Channel-maybe-commit-and-read}
attempts to read @var{octet-count} octets into @var{buffer}, starting
at @var{start-index}, from @var{channel}.
@code{Channel-maybe-commit-and-write} attempts to write
@var{octet-count} octets from @var{buffer}, starting at
@var{start-index}, to @var{channel}. @var{Condvar} is noted as waiting
for the completion of the I/O transaction. When the I/O transaction
finally completes --- in the case of a read, there are octets ready to
be read into @var{buffer} from @var{channel} or the end of the file was
struck; in the case of a write, @var{channel} is ready to receive some
octets ---, @var{condvar} is set to the result of the I/O transaction:
the number of octets read, an I/O error condition, or an EOF object,
for reads; and the number of octets written or an I/O error condition,
for writes.
@end deffn
@deffn procedure channel-maybe-commit-and-close channel closer @returns{} committed?
Attempts to commit the current proposal; if successful, this aborts any
wait on @var{channel}, sets the result of any condvars waiting on
@var{channel} to the EOF object, closes @var{channel} by applying
@var{closer} to @var{channel} (in theory, @var{closer} could be
anything; usually, however, it is @code{close-channel} from the
@code{channels} structure or some wrapper around it), and returns
@code{#t}. If the commit failed, @code{channel-maybe-commit-and-close}
immediately returns @code{#f}.
@end deffn
@deffn procedure channel-write channel buffer start-index octet-count @returns{} octet-count-written
Atomically attempts to write @var{octet-count} octets to @var{channel}
from @var{buffer}, starting at @var{start-index} in @var{buffer}. If
no I/O transaction immediately occurs --- what would result in
@code{channel-maybe-write} returning @code{#f} ---,
@code{channel-write} blocks until something does happen. It returns
the number of octets written to @var{channel}.
@end deffn
@deffn procedure wait-for-channel channel condvar @returns{} unspecified
Registers @var{condvar} so that it will be set to the result of some
prior I/O transaction when some I/O event regarding @var{channel}
occurs. (Contrary to the name, this does not actually wait or block.
One must still use @code{maybe-commit-and-wait-for-condvar} on
@var{condvar}; @pxref{Higher-level synchronization, condition
variables}.) This is useful primarily in conjunction with calling
foreign I/O routines that register channels with the VM's event polling
system.
@strong{Note:} @code{wait-for-channel} must be called with interrupts
disabled.
@c @xref{Interrupts}.
@end deffn
@node Channel ports
@subsection Channel ports
@stindex channel-ports
Built-in to Scheme48 are ports made atop channels. These are what are
created by R5RS's standard file operations. The following names are
exported by the @code{channel-ports} structure.
@deffn procedure call-with-input-file filename receiver @returns{} values
@deffnx procedure call-with-output-file filename receiver @returns{} values
@deffnx procedure with-input-from-file filename thunk @returns{} values
@deffnx procedure with-output-to-file filename thunk @returns{} values
@deffnx procedure open-input-file filename @returns{} input-port
@deffnx procedure open-output-file filename @returns{} output-port
Standard R5RS file I/O operations. (These are also exported by the
@code{scheme} structure.) The @code{call-with-...put-file} operations
open the specified type of port and apply @var{receiver} to it; after
@var{receiver} returns normally (@ie{} nothing is done if there is a
throw out of @var{receiver}), they close the port and return the
values that @var{receiver} returned. @code{With-input-from-file} &
@code{with-output-to-file} do similarly, but, rather than applying
@var{thunk} to the port, they dynamically bind the current input &
output ports, respectively, to the newly opened ports.
@code{Call-with-input-file}, @code{call-with-output-file},
@code{with-input-from-file}, and @code{with-output-to-file} return the
values that @var{thunk} returns. @code{Open-input-file} &
@code{open-output-file} just open input & output ports; users of these
operations must close them manually.
@end deffn
@deffn procedure input-channel->port channel [buffer-size] @returns{} port
@deffnx procedure output-channel->port channel [buffer-size] @returns{} port
These create input & output ports atop the given channels and optional
buffer sizes. The default buffer size is 4096 bytes.
@end deffn
@deffn procedure input-channel+closer->port channel closer [buffer-size] @returns{} port
@deffnx procedure output-channel+closer->port channel closer [buffer-size] @returns{} port
Similarly, these create input & output ports atop the given channels
and optional buffer sizes, but they allow for extra cleanup when the
resulting ports are closed.
@end deffn
@cindex port to channel conversion
@cindex accessing file ports' channels
@deffn procedure port->channel port @returns{} channel or @code{#f}
If @var{port} is a port created by the system's channel ports facility,
@code{port->channel} returns the channel it was created atop; otherwise
@code{port->channel} returns @code{#f}.
@end deffn
@deffn procedure force-channel-output-ports! @returns{} unspecified
This attempts to force as much output as possible from all of the ports
based on channels. This is used by Scheme48's POSIX libraries before
forking the current process.
@end deffn
|