Note: This website is archived. For up-to-date information about D projects and development, please visit wiki.dlang.org.

DReactor is a multi-threaded event dispatching framework. It is designed for massive scalability in handling any manner of IO events, such as network, file etc.

At the core of the system is a Vat. This concept was inspired by the similar construct found in E (1) At it's most fundamental level, it is a Polling loop running in its own thread. At the high level, it is the thread of execution for all IO on the resources that it manages. (2).

The Vat dispatches all events through a Dispatcher. This object is a container for all potential events types a resource may encouner. This allows the power and simplicity of a Vat handling many types of connections and events at once, while allowing the flexibility to deal with each connection/event in an individual manner.

The Dispatcher also has inheritance characteristics. A Protocol or service may choose to pass down event handling attributes from parent Dispatcher to child, so they don't have to go through the hassle of re-registering callbacks for each event type.

One other note, since outbound data must be handled by the Vat, and only when the resource is available to receive it, Dispatchers also manage outbound buffers and, by default, respond to such events by the Vat.

At a higher level, there are Protocols. These utilize the Dispatchers to provide state management and event handling to the system. DReactor currently comes with RawTCP and RawUdp?, which contain Client and Listener classes (I try to avoid the term "Server", since in modern SOA, nearly everything is both a Client and a Server). These classes manage simple send and receive logic, and are suitable for a wide variety of network IO.

Example:

module longtest;

import tango.net.Socket;
import tango.core.Thread;
import tango.io.Stdout;
import dreactor.core.Vat; 
import dreactor.core.Dispatcher;
import dreactor.protocol.RawTcp;
import dreactor.transport.AsyncSocketConduit;


int main()
{
    // Create and start the listener
    AsyncSocketConduit cond = new AsyncSocketConduit;
    Dispatcher ld = new Dispatcher(cond, true);
    Vat l_vat = new Vat();
    RawTCPListener listener = new RawTCPListener(ld, l_vat, new IPv4Address(5555)); 
    l_vat.run();

    // Create and start the client
    AsyncSocketConduit clcond = new AsyncSocketConduit;
    Dispatcher cd = new Dispatcher(clcond);
    Vat c_vat = new Vat();
    RawTCPClient client = new RawTCPClient(cd, c_vat);
    c_vat.run(); //run, vat, run!

    // Connect and send
    client.connect(new IPv4Address("localhost", 5555));
    client.send("This is a test");
    return 0;
}

This simple example shows the creation of a listener vat, and a client vat. Each is populated with a SocketConduit? and a Dispatcher.

NOTE: for such arrangements, the interface can actually be made much simpler, The RawTCPClient will default to creating an AsyncSocketConduit? and a Dispatcher and supply it the default handlers. I chose to be explicit to demonstrate how all of the pieces fit together.

Next check out the DreactorTutorial where we take this example and turn it into a useful chat server.

(1) - See http://erights.org/

(2) - This is partially because I think it's a good design, but mostly because it is a requirement for EPoll (and probably others) that sockets should be polled in the same thread in which they're read-from and written-to.