Boost logo

Boost :

From: Hamish Mackenzie (hamish_at_[hidden])
Date: 2002-11-25 08:03:26


On Mon, 2002-11-25 at 10:30, Markus Schöpflin wrote:
> And I think it would be really important to provide a clean
> interaction model between the socket library and the thread library
> and a clean solution to the problems that keep on coming up again and
> again when doing socket programming. From the top of my head:
>
> - How to interupt a thread waiting on some socket event (synchronous
> and asynchronous) from another thread?
>
> - How do you wait for more than just socket events? Thread conditions,
> window messages, ...
>

Could we accomplish the first by solving the second and having some kind
of "interrupt" event source

Could we do something like

class event_source_set
{
public:
        void insert( const interrupt_event_source & e );
        void insert( const user_interface_event_source & e );
        void insert( const socket_read_event_source & e );
        void insert( const socket_write_event_source & e );

        template< typename Event_Sink_Type >
        void process_events( Event_Sink_Type & sink );

        template< typename Event_Sink_Type >
        void process_events( Event_Sink_Type & sink, timeout_type t );
...
};

The caller would do this

class my_event_sink
{
public
        void event( const interrupt_event & e )
        {
                throw interrupted_exception;
        }
        void event( const user_interface_event & e );
        void event( const socket_read_event & e );
        void event( const socket_write_event & e );
...
};

void f()
{
        my_event_sink sink;
        event_source_set event_sources;
        event_sources.insert( interrupt_event_source() );
        event_sources.insert( socket_read_event( s ) );
        ...

        while( !sink.done() )
        {
                event_sources.process_events( my_event_sink );
        }
}

process_events would wait (using select or WaitForMultipleObjects) then
call the event member of the sink for each event in turn.

In order for it to work with blocking io we could simulate blocking io
using non-blocking.

class simple_send_event_sink
{
public
    blocking_send_event_sink( void * d, int len )
        : data_( (unsigned char *) d ),
          length_( len ),
          bytes_written( 0 ) {}
    void event( const interrupt_event & e )
    {
        throw interrupted_exception;
    }
    void event( const socket_write_event & e )
    {
        int n = e.socket().send( data_ + bytes_written_, remaining() );
        assert( n > 0 );
        bytes_written_ += n;
    }
    int remaining() const { return length_ - bytes_written_; }
    int result() const { return bytes_written_; }
private:
    unsigned char * data_;
    int length_;
    int bytes_written_;
};

class blocking_socket
{
    socket non_blocking_socket_;

public:
    int send( void * data, int len )
    {
        simple_send_event_sink sink( data, len );

        event_source_set sources;
        sources.insert( interrupt_event_source() );
        sources.insert(
            socket_write_event_source( non_blocking_socket_ ) );

        while( sink.remaining() != 0 )
        {
            sources.process_events( sink );
        }

        return sink.result();
    }
...
};


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk