Device Adapters |
Device adapters are lightweight
mechanisms that provide a uniform interface for manipulating and communicating
with I/O devices. Derived from the abstract base class os_device
, each device adapter translates a set of primitive operations from the raw
device-specific interface to a generic interface. All parameters, return values,
and error conditions are converted as needed. This translation promotes
development of generic communication facilities that are independent of the
underlying transport mechanism.
Recursion Software provides device adapters for a variety of I/O devices including adapters for some ANSI/ISO C++ standard devices. While most device adapters are packaged with I/O components like File<ToolKit> or Network<ToolKit>, other device adapters may be available on our Web site at www.recursionsw.com.
The os_adapter
class is a reference-counting smart-pointer that manages device adapters as
shown in the following figure. Use the function os_adapter_for()
to create an os_adapter for a particular I/O
device.

The following example constructs
the correct device adapter for an fstream device.
fstream file( "file.out", ios::out | ios::trunc );
os_adapter adapter = os_adapter_for( file );
For convenience, many Recursion
Software I/O classes supply a conversion operator that acts as a factory for the
necessary os_adapter so you can omit the call to os_adapter_for()
. The following example constructs the correct device adapter for an os_tcp_socket
.
os_tcp_socket socket;
os_adapter adapter = socket;
The device adapter interface
defines a set of relatively low-level operations common across most devices.
Because certain operations, such as repositioning, may not be available on all
devices, the interface allows any operation to fail due to device limitations.
The types of operations defined by the os_device
interface fall into the following categories.
To add support for your device,
create a subclass of os_device and specify the
appropriate operation translations. Note that you must ensure your new class
does not throw exceptions. Then create a global factory function os_adapter_for
for the new device adapter.
For more information about the
device adapter interface, refer to the os_device
entry in the class catalog.
The following example demonstrates
how to use device adapters to write to, reposition, and read from different I/O
devices. The functions output() and input()
write and read a text string to each device using the generic interface.
Note that adapter behaviors are
invoked using operator-> on an os_adapter
. This operator performs an efficient, inline forward to the os_device
that is managed by the os_adapter . This is a
general reference-counting technique and prevents the need to copy os_device
-based objects.
#include <fstream>
#include <ospace/file.h>
#include <ospace/stream.h>
char* original = "Systems< ToolKit > os_adapter example.";
void
output( const os_adapter& adapter )
{
adapter->write( original, strlen( original ) + 1 );
adapter->sync();
}
void
input( const os_adapter& adapter )
{
char duplicate[ 50 ];
// Null terminate the buffer in case there is an error.
duplicate[ 0 ] = 0;
int bytes = adapter->read( duplicate, sizeof( duplicate ) );
cout << "Read: " << duplicate << endl;
if ( bytes <= 0 || strcmp( original, duplicate ) != 0 )
{
cout << "Error: strings do not match!" << endl;
cout << "\tbytes = " << bytes << endl;
cout << "\toriginal = " << original << endl;
cout << "\tduplicate = " << duplicate << endl;
}
}
void
main()
{
os_file_toolkit init_file;
os_streaming_toolkit init_streaming;
cout << "Opening devices." << endl;
os_buffer buf1;
os_file txt1( "adapter.1", O_CREAT | O_TRUNC, O_RDWR );
fstream txt2( "adapter.2", ios::in | ios::out | ios::trunc );
cout << "Creating generic adapters for each device." << endl;
os_adapter binary( os_adapter_for( buf1 ) );
os_adapter file( os_adapter_for( txt1 ) );
os_adapter stream( os_adapter_for( txt2 ) );
cout << "Writing to adapters." << endl;
output( binary );
output( file );
output( stream );
cout << "Seeking to beginning." << endl;
binary->seek( 0 );
file->seek( 0 );
stream->seek( 0 );
cout << "Reading from adapters." << endl;
input( binary );
input( file );
input( stream );
cout << "Closing devices." << endl;
binary->close();
file->close();
stream->close();
}
Opening devices.
Creating generic adapters for each device.
Writing to adapters.
Seeking to beginning.
Reading from adapters.
Read: Systems< ToolKit > os_adapter example.
Read: Systems< ToolKit > os_adapter example.
Read: Systems< ToolKit > os_adapter example.
Closing devices.
Copyright©1994-2026 Recursion
Software LLC
All Rights Reserved - For use by licensed users only.