view dreactor/core/Dispatcher.d @ 11:5836613d16ac

reorg! reorg!
author rick@minifunk
date Tue, 12 Aug 2008 16:59:56 -0400
parents 5412a1ff2e49
children
line wrap: on
line source

module dreactor.protocol.Dispatcher;

import tango.io.selector.model.ISelector;
import tango.util.collection.CircularSeq;
import tango.net.Socket;
public  import  tango.core.Exception;
import dreactor.transport.AsyncSocketConduit;

import tango.util.log.Log;
import tango.util.log.Config;

class Dispatcher
{
public
    this (Conduit trans)
    {
        cond = trans;
        ibuf_len = 0;
        o_offset = 0;
        out_buffers = new CircularSeq!(char[]);
        log = Log.lookup("dreactor.core.Dispatcher");
    }
    
    /**************************************************************************

        onSend  -- Send method
        Called by the vat in response to a FD writeable event. 
        Sends data, returns amount sent. Unregisters Handler for sending
        if there is no more data left to send. 

    ***************************************************************************/
    public int onSend()
    {
        Logger log = Log.lookup("Handlers.onSend");
     
        char[] outbuf = nextBuffer();
        if (outbuf !is null)
        {
            int sent = cond.write(outbuf);
            if (sent > 0)
            {
                if (! addOffset(sent))
                {
                    return UNREGISTER;
                }
            }
            else if (sent == 0)
            {
                log.error("Select said socket was writable, but sent 0 bytes");
            }
            else
            {
               log.error("Socket send return ERR {}", sent);
            }
            return REMAIN;
        }
        else
        {
            return UNREGISTER;
        }
    }

    /**************************************************************************
    
        appendOutBuffer

        Adds an outgoing buffer to the list. This returns true if the list
        was empty, indicating that the handler should be registered with the
        SelectLoop. If it returns false, it was probably already registered.
        
    **************************************************************************/
    bool appendOutBuffer(char[] outbuf)
    {
        out_buffers.append(outbuf);
        out_buffers_len++;
        if (out_buffers_len == 1)
            return true;
        else
            return false;
    }
    
    /**************************************************************************

        addOffset 
        Use this function to update the offset position after a successful data
        send. This not only manages the current offset, but will update the 
        out buffer chain if necessary. 

        Returns: false if there is nothing left to send, true if there is.

    **************************************************************************/ 
    bool addOffset(int off)
    in
    {
        assert(out_buffers_len > 0);
    }
    body
    {
        char[] hd = out_buffers.head();
        if ((off + o_offset) >= hd.length)
        {
            out_buffers.removeHead();
            o_offset = 0;
            out_buffers_len--;
            return (out_buffers_len > 0);
        }
        else
            o_offset += off;
        return true;
    }
    
    /**************************************************************************

        char[] nextBuffer

        Returns a slice of the current outbound buffer, returns a char[] pointing
        to null if there is no current outbound buffer

    **************************************************************************/
    synchronized char[] nextBuffer()
    {
        if (out_buffers_len < 1)
        {
            return null; 
        }

        return out_buffers.head()[o_offset .. $];
    }

    Conduit cond; 
    CircularSeq!(char[]) out_buffers;
    int out_buffers_len;
    int ibuf_len;
    int o_offset;
    Logger log; 
}