Let me know if this helps:
// dependenciestemplate <T> class pool;class socket;class socket::multi;using std::stringstream;using std::istream;using std::ostream;using std::setw; socket::multi socketmultibuffer; class isocketstream{ string& buffer; stringstream stream; public: socketstream () : buffer (socketmultibuffer.get_input ()) {} ~socketstream () { socketmultibuffer.release_input (&buffer); } operator istream& () { return stream; }}; class osocketstream{ string& buffer; stringstream stream; public: osocketstream () : buffer (socketmultibuffer.get_output ()) {} ~osocketstream () { socketmultibuffer.release_output (&buffer); } operator ostream& () { return stream; }}; typedef pool <osocketstream> output_stream_pool;typedef pool <isocketstream> input_stream_pool; output_stream_pool output_streams (20); input_stream_pool input_streams (20); template <class T, pool <T>& P > class pooled_object{ T& t; public: pooled_object () : t (P.create ()) {} ~pooled_object () { P.destroy (t); } operator T& () { return t; }}; typedef pooled_object <osocketstream, output_streams> pooled_ostream;typedef pooled_object <isocketstream, input_streams> pooled_istream; class character{ int big, small; public: void send () { serialize (pooled_istream ()); } void receive () { serialize (pooled_ostream ()); } protected: virtual void serialize (ostream& out) { out << setw(10) << big << setw(5) << small; } virtual void serialize (istream& in) { in >> big >> small; }}; class player{ int x, y; protected: virtual void serialize (ostream& out) { character::serialize(out); out << x << y; } virtual void serialize (ostream& in) { character::serialize(in); in >> x >> y; }};
The pool template manages a pool of type T and allows you to reserve an element for your own use and release it back to the system when you are done. socket is a class that encapsulates socket operations. socketmultibuffer is an instance of a class that adapts the simple socket class to add support for multiple input/output buffers, then encapsulates the combining of the multiple input/output streams them into a single input/output stream for send/receive using the socket class interface. socketmultibuffer manages multiple buffers, which are exposed by the socketmultibuffer.get_input/get_output and socketmultibuffer.release_input/release_output functions.
The isocketstream and osocketstream abstract socketmulti's support for multiple buffers and provide a standard istream/ostream interface by containing a stringstream object and exposing its istream/ostream interface. The stringstream object gets its buffer from the socketmultibuffer class, and leaves the details of combining the multiple streams in socketmultibuffer's implementation. The isocketstream/osocketstream classes should be separate, because the socketmultibuffer class allows a buffer to be either input or output, but not both.
Creating a pool of socket streams is easy now, just use the typedef and instantiate the pool with the initial capacity. I used two pools, one for input and one for output. To encapsulate the fact that the streams are in a pool, I placed them into a pooled_object template class which simply creates a pool object of type T from pool instance P, and then created typedefs so that the template parameters were hidden behind type names. The pooled_object's destructor takes care of destroying the object.
Retrieving one of these pooled streams is simplicity itself; you just instantiate a pooled_istream or pooled_ostream, which goes through the chain of adaptation code, eventually reserving a buffer, presenting a standard stream interface, etc. The character send/receive functions are used to serialize data across a socket, so they call the overloaded serialize virtual member functions to perform input and output. Remember to call any immediate base classes versions of serialize from within a derived class's serialize functions, and everything should go smoothly.
Since the pooled_istream and pooled_ostream classes provide a conversion operator to std::istream and std::ostream, you can design the serialize functions to use std::istream and std::ostream, while passing a pooled_istream/pooled_ostream object, in which case the conversion allowed by the operator istream&/ostream& will give you the stringstream interface to the multiple i/o socket buffers.
Simple, eh? The serialize member functions are borrowed from MFC's CArchive class, the adaptors from The C++ Programming Language, Special Edition, and the pool data structure from Magmai's post.
EDIT: Changed behavior of pool slightly to contain capacity for streams rather than actual streams, and also changed the pooled_object typedef so that it works.
Edited by - null_pointer on January 15, 2002 9:39:26 AM