ACE
6.1.0
|
Create your custom streambuf by providing and ACE_*_Stream object to this template. I have tested it with ACE_SOCK_Stream and it should work fine for others as well. More...
#include <IOStream.h>
Public Member Functions | |
virtual | ~ACE_Streambuf (void) |
ACE_Time_Value * | recv_timeout (ACE_Time_Value *tv=0) |
Get the current Time_Value pointer and provide a new one. | |
char * | reset_put_buffer (char *newBuffer=0, u_int _streambuf_size=0, u_int _pptr=0) |
u_int | put_avail (void) |
char * | reset_get_buffer (char *newBuffer=0, u_int _streambuf_size=0, u_int _gptr=0, u_int _egptr=0) |
u_int | get_waiting (void) |
u_int | get_avail (void) |
u_int | streambuf_size (void) |
Query the streambuf for the size of its buffers. | |
u_char | timeout (void) |
Protected Member Functions | |
ACE_Streambuf (u_int streambuf_size, int io_mode) | |
virtual int | sync (void) |
virtual int | underflow (void) |
virtual int | overflow (int c=EOF) |
void | reset_base (void) |
int | syncin (void) |
int | syncout (void) |
int | flushbuf (void) |
int | fillbuf (void) |
virtual int | get_one_byte (void) |
virtual ssize_t | send (char *buf, ssize_t len)=0 |
virtual ssize_t | recv (char *buf, ssize_t len, ACE_Time_Value *tv=0)=0 |
virtual ssize_t | recv (char *buf, ssize_t len, int flags, ACE_Time_Value *tv=0)=0 |
virtual ssize_t | recv_n (char *buf, ssize_t len, int flags=0, ACE_Time_Value *tv=0)=0 |
virtual ACE_HANDLE | get_handle (void) |
Protected Attributes | |
char * | eback_saved_ |
char * | gptr_saved_ |
char * | egptr_saved_ |
char * | pbase_saved_ |
char * | pptr_saved_ |
char * | epptr_saved_ |
u_char | cur_mode_ |
const u_char | get_mode_ |
const u_char | put_mode_ |
int | mode_ |
const u_int | streambuf_size_ |
u_char | timeout_ |
Did we take an error because of an IO operation timeout? | |
ACE_Time_Value | recv_timeout_value_ |
ACE_Time_Value * | recv_timeout_ |
Create your custom streambuf by providing and ACE_*_Stream object to this template. I have tested it with ACE_SOCK_Stream and it should work fine for others as well.
For any iostream object, the real work is done by the underlying streambuf class. That is what we create here. A streambuf has an internal buffer area into which data is read and written as the iostream requests and provides data. At some point during the read process, the iostream will realize that the streambuf has no more data. The underflow function of the streambuf is then called. Likewise, during the write process, the iostream will eventually notice that the streabuf's buffer has become full and will invoke the overflow function. The empty/full state of the read/write "buffers" are controled by two sets pointers. One set is dedicated to read, the other to write. These pointers, in turn, reference a common buffer that is to be shared by both read and write operations. It is this common buffer to which data is written and from which it is read. The common buffer is used by functions of the streambuf as well as the iostream. Because of this and the fact that it is "shared" by both read and write operators, there is a danger of data corruption if read and write operations are allowed to take place "at the same time". To prevent data corruption, we manipulate the read and write pointer sets so that the streambuf is in either a read-mode or write-mode at all times and can never be in both modes at the same time. In the constructor: set the read and write sets to NULL This causes the underflow or overflow operators to be invoked at the first IO activity of the iostream. In the underflow function we arrange for the common buffer to reference our read buffer and for the write pointer set to be disabled. If a write operation is performed by the iostream this will cause the overflow function to be invoked. In the overflow function we arrange for the common buffer to reference our write buffer and for the read pointer set to be disabled. This causes the underflow function to be invoked when the iostream "changes our mode". The overflow function will also invoke the send_n function to flush the buffered data to our peer. Similarly, the sync and syncout functions will cause send_n to be invoked to send the data. Since socket's and the like do not support seeking, there can be no method for "syncing" the input. However, since we maintain separate read/write buffers, no data is lost by "syncing" the input. It simply remains buffered.
ACE_Streambuf::~ACE_Streambuf | ( | void | ) | [virtual] |
If the default allocation strategy were used the common buffer would be deleted when the object destructs. Since we are providing separate read/write buffers, it is up to us to manage their memory.
ACE_Streambuf::ACE_Streambuf | ( | u_int | streambuf_size, |
int | io_mode | ||
) | [protected] |
int ACE_Streambuf::fillbuf | ( | void | ) | [protected] |
fillbuf is called in a couple of places. This is the worker of underflow. It will attempt to fill the read buffer from the peer.
int ACE_Streambuf::flushbuf | ( | void | ) | [protected] |
flushbuf() is the worker of syncout. It is a separate function because it gets used sometimes in different context.
u_int ACE_Streambuf::get_avail | ( | void | ) |
Return the number of bytes in the get area (includes some already gotten); eback + get_avail = egptr
ACE_HANDLE ACE_Streambuf::get_handle | ( | void | ) | [protected, virtual] |
Reimplemented in ACE_Streambuf_T< STREAM >.
int ACE_Streambuf::get_one_byte | ( | void | ) | [protected, virtual] |
Used by fillbuf and others to get exactly one byte from the peer. recv_n is used to be sure we block until something is available. It is virtual because we really need to override it for datagram-derived objects.
u_int ACE_Streambuf::get_waiting | ( | void | ) |
Return the number of bytes not yet gotten. eback + get_waiting = gptr
int ACE_Streambuf::overflow | ( | int | c = EOF | ) | [protected, virtual] |
The overflow function receives the character which caused the overflow.
u_int ACE_Streambuf::put_avail | ( | void | ) |
Return the number of bytes to be 'put' onto the stream media. pbase + put_avail = pptr
virtual ssize_t ACE_Streambuf::recv | ( | char * | buf, |
ssize_t | len, | ||
ACE_Time_Value * | tv = 0 |
||
) | [protected, pure virtual] |
Implemented in ACE_Streambuf_T< STREAM >.
virtual ssize_t ACE_Streambuf::recv | ( | char * | buf, |
ssize_t | len, | ||
int | flags, | ||
ACE_Time_Value * | tv = 0 |
||
) | [protected, pure virtual] |
Implemented in ACE_Streambuf_T< STREAM >.
virtual ssize_t ACE_Streambuf::recv_n | ( | char * | buf, |
ssize_t | len, | ||
int | flags = 0 , |
||
ACE_Time_Value * | tv = 0 |
||
) | [protected, pure virtual] |
Implemented in ACE_Streambuf_T< STREAM >.
ACE_Time_Value * ACE_Streambuf::recv_timeout | ( | ACE_Time_Value * | tv = 0 | ) |
Get the current Time_Value pointer and provide a new one.
void ACE_Streambuf::reset_base | ( | void | ) | [protected] |
Resets the <base> pointer and streambuf mode. This is used internally when get/put buffers are allocatd.
char * ACE_Streambuf::reset_get_buffer | ( | char * | newBuffer = 0 , |
u_int | _streambuf_size = 0 , |
||
u_int | _gptr = 0 , |
||
u_int | _egptr = 0 |
||
) |
Use this to allocate a new/different buffer for get operations. If you do not provide a buffer pointer, one will be allocated. That is the preferred method. If you do provide a buffer, the size must match that being used by the put buffer. If successful, you will receive a pointer to the current get buffer. It is your responsibility to delete this memory when you are done with it.
char * ACE_Streambuf::reset_put_buffer | ( | char * | newBuffer = 0 , |
u_int | _streambuf_size = 0 , |
||
u_int | _pptr = 0 |
||
) |
Use this to allocate a new/different buffer for put operations. If you do not provide a buffer pointer, one will be allocated. That is the preferred method. If you do provide a buffer, the size must match that being used by the get buffer. If successful, you will receive a pointer to the current put buffer. It is your responsibility to delete this memory when you are done with it.
Stream connections and "unconnected connections" (ie -- datagrams) need to work just a little differently. We derive custom Streambuf objects for them and provide these functions at that time.
Implemented in ACE_Streambuf_T< STREAM >.
u_int ACE_Streambuf::streambuf_size | ( | void | ) |
Query the streambuf for the size of its buffers.
int ACE_Streambuf::sync | ( | void | ) | [protected, virtual] |
Sync both input and output. See syncin/syncout below for descriptions.
int ACE_Streambuf::syncin | ( | void | ) | [protected] |
syncin is called when the input needs to be synced with the source file. In a filebuf, this results in the <seek> system call being used. We can't do that on socket-like connections, so this does basically nothing. That's safe because we have a separate read buffer to maintain the already-read data. In a filebuf, the single common buffer is used forcing the <seek> call.
int ACE_Streambuf::syncout | ( | void | ) | [protected] |
syncout() is called when the output needs to be flushed. This is easily done by calling the peer's send_n function.
u_char ACE_Streambuf::timeout | ( | void | ) |
Did we take an error because of an IO operation timeout?
int ACE_Streambuf::underflow | ( | void | ) | [protected, virtual] |
u_char ACE_Streambuf::cur_mode_ [protected] |
char* ACE_Streambuf::eback_saved_ [protected] |
char* ACE_Streambuf::egptr_saved_ [protected] |
char* ACE_Streambuf::epptr_saved_ [protected] |
const u_char ACE_Streambuf::get_mode_ [protected] |
char* ACE_Streambuf::gptr_saved_ [protected] |
int ACE_Streambuf::mode_ [protected] |
mode tells us if we're working for an istream, ostream, or iostream.
char* ACE_Streambuf::pbase_saved_ [protected] |
char* ACE_Streambuf::pptr_saved_ [protected] |
const u_char ACE_Streambuf::put_mode_ [protected] |
ACE_Time_Value* ACE_Streambuf::recv_timeout_ [protected] |
ACE_Time_Value ACE_Streambuf::recv_timeout_value_ [protected] |
We want to allow the user to provide Time_Value pointers to prevent infinite blocking while waiting to receive data.
const u_int ACE_Streambuf::streambuf_size_ [protected] |
This defines the size of the input and output buffers. It can be set by the object constructor.
u_char ACE_Streambuf::timeout_ [protected] |
Did we take an error because of an IO operation timeout?