NAME ^

docs/pdds/pdd22_io.pod - Parrot I/O

ABSTRACT ^

Parrot's I/O subsystem.

VERSION ^

$Revision$

DEFINITIONS ^

A "stream" allows input or output operations on a source/destination such as a file, keyboard, or text console. Streams are also called "filehandles", though only some of them have anything to do with files.

DESCRIPTION ^

This document defines Parrot's I/O subsystem, for both streams and network I/O. Parrot has both synchronous and asynchronous I/O operations. This section describes the interface, and the IMPLEMENTATION section provides more details on general implementation questions and error handling.

The signatures for the asynchronous operations are nearly identical to the synchronous operations, but the asynchronous operations take an additional argument for a callback, and the only return value from the asynchronous operations is a status object. When the callbacks invoked, they are passed the status object as their sole argument. Any return values from the operation are stored within the status object.

The listing below says little about whether the opcodes return error information. For now assume that they can either return a status object, or return nothing. Error handling is discussed more thoroughly in the implementation section.

I/O Stream Opcodes ^

Opening and closing streams

Retrieving existing streams

These opcodes do not have asynchronous variants.

Writing to streams

Reading from streams

Retrieving and setting stream properties

Deprecated opcodes

Filesystem Opcodes ^

Network I/O Opcodes ^

Most of these opcodes conform to the standard UNIX interface, but the layer API allows alternate implementations for each.

IMPLEMENTATION ^

The Parrot I/O subsystem uses a per-interpreter stack to provide a layer-based approach to I/O. Each layer implements a subset of the ParrotIOLayerAPI vtable. To find an I/O function, the layer stack is searched downwards until a non-NULL function pointer is found for that particular slot. [We need to look into the implementation of IO layers for simplifications.]

Synchronous and Asynchronous Operations ^

Currently, Parrot only implements synchronous I/O operations. For the 1.0 release the asynchronous operations will be implemented separately from the synchronous ones. [Eventually there may be an implementation that uses one variant to implement the other, but it's not an immediate priority.]

Asynchronous operations don't use Parrot threads, they use a light-weight concurrency model for asynchronous operations. The asynchronous I/O implementation will use Parrot's I/O layer architecture so some platforms can take advantage of their built-in asynchronous operations instead of using Parrot's concurrency implementation.

Communication between the calling code and the asynchronous operation thread will be handled by a shared status object. The operation thread will update the status object whenever the status changes, and the calling code can check the status object at any time. The status object contains a reference to the returned result of an asynchronous I/O call.

Synchronous opcodes are differentiated from asynchronous opcodes by the presence of a callback argument in the asynchronous calls. Asynchronous calls that don't supply callbacks (perhaps if the user wants to manually check later if the operation succeded) are enough of a fringe case that they don't need opcodes. They can access the functionality via methods on ParrotIO objects.

Error Handling ^

Currently some of the networking opcodes (connect, recv, send, poll, bind, and listen) return an integer indicating the status of the call, -1 or a system error code if unsuccessful. Other I/O opcodes (such as getfd and accept) have various different strategies for error notification, and others have no way of marking errors at all. We want to unify all I/O opcodes so they use a consistent strategy for error notification.

Synchronous operations

Synchronous I/O operations return an integer status code indicating success or failure in addition to their ordinary return value(s). This approach has the advantage of being lightweight: returning a single additional integer is cheap.

[Discuss: should synchronous operations take the same error handling strategy as asynchronous ones?]

Asynchronous operations

Asynchronous I/O operations return a status object. The status object contains an integer status code, string status/error message, and boolean success value.

An error callback may be set on a status object, though it isn't required. This callback will be invoked if the asynchronous operation terminates in an error condition. The error callback takes one argument, which is the status object containing all information about the failed call. If no error callback is set, then the standard callback will be invoked, and the user will need to check for error conditions in the status object as the first operation of the handler code.

Exceptions

At some point in the future, I/O objects may also provide a way to throw exceptions on error conditions. This feature will be enabled by calling a method on the I/O object to set an internal flag. The exception throwing will be implemented as a method call on the status object.

Note that exception handlers for asynchronous I/O operations will likely have to be set at a global scope because execution will have left the dynamic scope of the I/O call by the time the error occurs.

IPv6 Support ^

The transition from IPv4 to IPv6 is in progress, though not likely to be complete anytime soon. Most operating systems today offer at least dual-stack IPv6 implementations, so they can use either IPv4 or IPv6, depending on what's available. Parrot also needs to support either protocol. For the most part, the network I/O opcodes should internally handle either addressing scheme, without requiring the user to specify which scheme is being used.

IETF recommends defaulting to IPv6 connections and falling back to IPv4 connections when IPv6 fails. This would give us more solid testing of Parrot's compatibility IPv6, but may be too slow. Either way, it's a good idea to make setting the default (or selecting one exclusively) an option when compiling Parrot.

The most important issues for Parrot to consider with IPv6 are:

See the relevant IETF RFCs: "Application Aspects of IPv6 Transition" (http://www.ietf.org/rfc/rfc4038.txt) and "Basic Socket Interface Extensions for IPv6" (http://www.ietf.org/rfc/rfc3493.txt).

ATTACHMENTS ^

None.

FOOTNOTES ^

None.

REFERENCES ^

  src/io/io.c
  src/ops/io.ops
  include/parrot/io.h
  runtime/parrot/library/Stream/*
  src/io/io_unix.c
  src/io/io_win32.c
  Perl 5's IO::AIO
  Perl 5's POE


parrot