| Previous Chapter | Next Section | Table of Contents | Glossary | Index |
Clozure CL streams have an external-encoding attribute that may be read using STREAM-EXTERNAL-ENCODING and set using (SETF STREAM-EXTERNAL-ENCODING).
OPEN and
MAKE-SOCKET have each been extended to take
the additional keyword arguments: :CLASS,
:SHARING, and
:BASIC.
:CLASS
A symbol that names the desired class of the stream.
The specified class must inherit from
FILE-STREAM for
OPEN.
:SHARING
Specifies how a stream can be used by multiple
threads. The possible values are:
:PRIVATE, :LOCK and
:EXTERNAL. :PRIVATE is
the default. NIL is also accepted as a
synonym for :EXTERNAL.
:PRIVATE
Specifies that the stream can only be accessed by the thread that created it. This is the default. (There was some discussion on openmcl-devel about the idea of "transferring ownership" of a stream; this has not yet been implemented.) Attempts to do I/O on a stream with :PRIVATE sharing from a thread other than the stream's owner yield an error.
:LOCK
Specifies that all access to the stream require the calling thread to obtain a lock. There are separate "read" and "write" locks for IO streams. This makes it possible for instance, for one thread to read from such a stream while another thread writes to it. (see also make-read-write-lock with-read-lock with-write-lock)
:EXTERNAL
Specifies that I/O primitives enforce no access protocol. This may be appropriate for some types of application which can control stream access via application-level protocols. Note that since even the act of reading from a stream changes its internal state (and simultaneous access from multiple threads can therefore lead to corruption of that state), some care must be taken in the design of such protocols.
:BASIC
A boolean that indicates whether or not the stream is
a Gray stream, i.e. whether or not the stream is an instance
of FUNDAMENTAL-STREAM or
CCL::BASIC-STREAM(see Section 9.1.3, “Basic Versus Fundamental Streams”). Defaults to
T.
Gray streams (see Section 9.2, “Creating Your Own Stream Classes with Gray Streams”)
all inherit from FUNDAMENTAL-STREAM whereas
basic streams inherit from CCL::BASIC-STREAM.
The tradeoff between FUNDAMENTAL and BASIC streams is entirely
between flexibility and performance, potential or actual. I/O
primitives can recognize BASIC-STREAMs and exploit knowledge of
implementation details. FUNDAMENTAL stream classes can be
subclassed and extended in a standard way (the Gray streams
protocol).
For existing stream classes (FILE-STREAMs, SOCKETs, and the internal CCL::FD-STREAM classes used to implement file streams and sockets), a lot of code can be shared between the FUNDAMENTAL and BASIC implementations. The biggest difference should be that that code can be reached from I/O primitives like READ-CHAR without going through some steps that're there to support generality and extensibility, and skipping those steps when that support isn't needed can improve I/O performance.
The Gray stream method
STREAM-READ-CHAR should work on appropriate
BASIC-STREAMs. (There may still be cases
where such methods are undefined; such cases should be
considered bugs.) It is not guaranteed that Gray stream methods
would ever be called by I/O primitives to read a character from
a BASIC-STREAM, though there are still cases
where this happens.
A simple loop reading 2M characters from a text file runs
about 10X faster when the file is opened the new defaults
(:SHARING :PRIVATE :BASIC T) than it had
before these changes were made. That sounds good, until one
realizes that the "equivalent" C loop can be about 10X faster
still ...
A stream that is associated with a file descriptor has
attributes and accessors:
STREAM-INPUT-TIMEOUT,
STREAM-OUTPUT-TIMEOUT, and
STREAM-DEADLINE. All three accessors have
corresponding SETF methods.
STREAM-INPUT-TIMEOUT and
STREAM-OUTPUT-TIMEOUT are specified in
seconds and can be any positive real number less than one million.
When a timeout is set and the corresponding I/O operation takes
longer than the specified interval, an error is signalled. The
error is INPUT-TIMEOUT for input and
OUTPUT-TIMEOUT for output.
STREAM-DEADLINE specifies an absolute time in
internal-time-units. If an I/O operation on the stream does not
complete before the deadline then a
COMMUNICATION-DEADLINE-EXPIRED error is
signalled. A deadline takes precedence over any
input/output timeouts that may be set.
Historically, Clozure CL and MCL maintained a list of open
file streams in the value of
CCL:*OPEN-FILE-STREAMS*. This functionality
has been replaced with the thread-safe function:
CCL:OPEN-FILE-STREAMS and its two helper
functions: CCL:NOTE-OPEN-FILE-STREAM and
CCL:REMOVE-OPEN-FILE-STREAM. Maintaining
this list helps to ensure that streams get closed in an orderly
manner when the lisp exits.
| Previous Chapter | Next Section | Table of Contents | Glossary | Index |