view dreactor/core/SelectLoop.d @ 2:d3374d553986

updates
author rick@minifunk
date Thu, 12 Jun 2008 23:12:17 -0400
parents 7a315154bf5e
children e3dbc9208822
line wrap: on
line source

/*******************************************************************************

        copyright:      Copyright (c) 2008 Rick Richardson. All rights reserved

        license:        BSD style: $(LICENSE)

        version:        Initial release v0.1 : May 2008
        
        author:         Rick Richardson

*******************************************************************************/

module dreactor.core.SelectLoop;

import dreactor.transport.AsyncSocketConduit;
import tango.io.selector.Selector;
import tango.io.selector.model.ISelector;
import tango.core.Exception;
import tango.core.Thread;
import tango.core.Atomic;
import tango.util.collection.LinkSeq;
import tango.util.log.Log;
import tango.util.log.Configurator;

import dreactor.core.ConnectionHandler; 

Logger log = Log.getLogger("dreactor.core.SelectLoop");

static char[] version_string = "SelectLoop.d 0.1 2008-05-31";

class SelectLoop
{
private
    Thread thread;
    bool running;
    Atomic!(int) pending;
   
    ThreadSafeQueue!(ConnectionHandler) freshList; 
    //LinkSeq!(ConnectionHandler) connList;  probably not necessary

public    
    this()
    {
        freshList = new ThreadSafeQueue!(ConnectionHandler);
        //connList = new LinkSeq!(ConnectionHandler);
        Configurator();
    }

    void run()
    {
        running = true;
        thread = new Thread(&eventLoop);
        thread.start();
    }

    void exit()
    {
        running = false;
    }

    bool addConnection(ConnectionHandler handler)
    {
        return freshList.push(handler);       
    }

private
    void eventLoop()
    {
        auto selector = new Selector();
        selector.open();
        auto format = Log.format;         
        do
        {
            auto eventCount = selector.select(10);

            if (eventCount > 0)
            {
                // process events
                foreach (SelectionKey key; selector.selectedSet())
                {
                    if (key.isReadable())
                    {
                        // incoming data
                        auto conn = cast(ConnectionHandler) key.attachment;
                        if ( ConnectionHandler.listening == conn.getState() )
                            conn.handleConnection(conn.transport, addConnection);
                        else if ( ! conn.handleIncoming(conn.transport))
                            unregister(conn.transport);
                    }
                    else if (key.isWritable())
                    {
                        auto conn = cast(ConnectionHandler) key.attachment;
                        if ( ! conn.handleOutgoing(conn.transport))
                            unregister(conn.transport); 
                    }
                    else if (key.isHangup())
                    {
                        auto conn = cast(ConnectionHandler) key.attachment;
                        if ( ! conn.handleDisconnect(conn.transport))
                            unregister(conn.transport);
                    }
                    else if (key.isError() || key.isInvalidHandle())
                    {
                        // error, close connection
                        auto conn = cast(ConnectionHandler) key.attachment;
                        if ( ! conn.handleError(conn.transport, key.isInvalidHandle()))
                            selector.unregister(conn.transport);
                    }
                }
            }
            else if (eventCount == 0)
            {
                /* can't think of anything useful to do here. */
            }
            else
            {
                log.error(format("Selector.select returned {}", eventCount));
            }
            
            //add Conduits to listener
            freshList.processAll( (ConnectionHandler h)
            {
                selector.register(conn.transport, conn.events());
                //connList.append(conn); 
                return 1; 
            });
            //freshList.processAll(reg);

        } while (running)
    }
}