SEDNL  .
Simple Event Driven Network Library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Public Member Functions | Friends | List of all members
SedNL::EventListener Class Reference

Listen from events and incoming connections. More...

#include <EventListener.hpp>

Public Member Functions

 EventListener (TCPServer &server, unsigned int max_queue_size=1000)
 Construct an event listener from a TCPServer. More...
 
 EventListener (Connection &connection, unsigned int max_queue_size=1000)
 Construct an event listener from a Connection. More...
 
 EventListener (unsigned int max_queue_size=1000)
 Construct an empty listener. More...
 
 ~EventListener ()
 Destruct the event listener by calling join.
 
void attach (TCPServer &server) throw (std::bad_alloc, EventException)
 Add a server into the managed list. More...
 
void detach (TCPServer &server) throw (std::bad_alloc, EventException)
 Remove a server from the managed list. More...
 
void attach (Connection &connection) throw (std::bad_alloc, EventException)
 Add a connection into the managed list. More...
 
void detach (Connection &connection) throw (std::bad_alloc, EventException)
 Remove a connection from the managed list. More...
 
void run () throw (EventException)
 Launch the EventListener thread. More...
 
void join ()
 Join the EventListener thread. More...
 
Slot< Connection & > & on_connect ()
 Bind the connect event. More...
 

Friends

class Connection
 
class TCPServer
 
class EventConsumer
 

Detailed Description

Listen from events and incoming connections.

The EventListener class is one of the central class of SedNL. You should use it on server side to listen from incoming connections, and event from those connections.

You should also use it on client side to listen from events from TCPClient connections.

You can give as much TCPClient and TCPServer objects as you want to the same EventListener, it will handle all of them.

When a new connection is created, it produce a connect event which is immediately processed (which means that the listener thread will call the callback you put on the slot returned by on_connect()).

Then, every event comming from TCPConnection and Connections will be placed in queue (one queue by event name, placed in a deterministic order).

The next step is creating one or more EventConsumer that would be able to consume events stored in queue. This allow you to manage how much thread you want, and which events should be processed at the same time. For more information on this subject, see EventConsumer's documentation.

Here is a short example of what you can do with an EventListener.

//Connect to two different servers
TCPClient client1(SocketAddress("foo.net", 4242));
TCPClient client2(SocketAddress("bar.net", 4343));
//Listen to two different port
TCPServer server1(SocketAddress(5000));
TCPServer server2(SocketAddress(8000));
//Create an empty EventListener.
EventListener listener;
//Listen messages from foo and bar
listener.attach(client1);
listener.attach(client2);
//Listen from incoming connection in both port 5000 and port 8000.
//We do not differenciate connection from different ports.
listener.attach(server1);
listener.attach(server2);
//When a new user connect from server1 or server2.
//Lets says we allocate some memory to store informations
//related to this connection, and use Connection::set_user_data().
listener.on_connect(my_on_connect);
//We want to react on message from foo.net, bar.net, and users
//connected to port 5000 and 8000.
EventConsumer consumer(listener);
consumer.bind("on_hello").set_function(my_hello_stuff);
//We can imagine that we forward messages to foo.net or
//bar.net depending of the request.
consumer.bind("on_query_foo").set_function(my_query_foo_stuff);
consumer.bind("on_query_bar").set_function(my_query_bar_stuff);
consumer.bind("answer_from_bar").set_function(my_bar_answer_stuff);
consumer.bind("answer_from_foo").set_function(my_foo_answer_stuff);
//We are ready, and launch the listener thread
listener.run();
//We also launch the consumer thread
consumer.run();
//Now we can do what we want in the main thread.
//for example, providing commands from stdin.
//When we are done, we should close all connections.
listener.join();
consumer.join();

If in this example, you would need to differenciate messages from foo and messages from bar, you could check the address of the first parameter of you callback (Connection&). It is always a reference to the TCPClient object you given, casted to a Connection object.

So, you would do something like :

void on_something(Connection& c, const Event& e)
{
if(static_cast<Connection*>(&client1) == &c)
std::cout << "It's from foo." << std::endl;
if(static_cast<Connection*>(&client2) == &c)
std::cout << "It's from bar." << std::endl;
}

Definition at line 48 of file EventListener.hpp.

Constructor & Destructor Documentation

SedNL::EventListener::EventListener ( TCPServer server,
unsigned int  max_queue_size = 1000 
)

Construct an event listener from a TCPServer.

Does exactly the same thing as constructing an empty listener, and then calling attach(server).

Parameters
[in]serverThe server to listen.
[in]max_queue_sizeUpper bound of the size of an event queue.
SedNL::EventListener::EventListener ( Connection connection,
unsigned int  max_queue_size = 1000 
)

Construct an event listener from a Connection.

Since TCPClient is a connection, you can also call EventListener(TCPConnection &connection).

Does exactly the same thing as constructing an empty listener, and then calling attach(connection).

Parameters
[in]connectionThe connection to listen
[in]max_queue_sizeUpper bound of the size of an event queue.
SedNL::EventListener::EventListener ( unsigned int  max_queue_size = 1000)

Construct an empty listener.

You can allow bigguer queue size by setting max_queue_size to an other value. You can suppress the upper bound by setting max_queue_size to 0, but it's not recommended.

Parameters
[in]max_queue_sizeUpper bound of the size of an event queue.

Member Function Documentation

void SedNL::EventListener::attach ( TCPServer server)
throw (std::bad_alloc,
EventException
)

Add a server into the managed list.

Same behavior as attach() on a Connection object.

Parameters
[in]serverThe server to attach.
void SedNL::EventListener::attach ( Connection connection)
throw (std::bad_alloc,
EventException
)

Add a connection into the managed list.

The client will be kept by the EventListener. The object shouldn't be destructed before the EventLister. If you want to destruct it, you need to remove it from the "managed list" by calling detach().

A connection cannot be attached to two listener. Try to do it will result in an AlreadyListenned exception.

You can't call attach while the listener is runing. If you do so, it will through a EventListenerRunning exception.

Calling attach on a managed connection won't do anything.

Parameters
[in]connectionThe connection to attach.
void SedNL::EventListener::detach ( TCPServer server)
throw (std::bad_alloc,
EventException
)

Remove a server from the managed list.

Same behavior as detach() on a Connection object.

Parameters
[in]serverThe server to detach.
void SedNL::EventListener::detach ( Connection connection)
throw (std::bad_alloc,
EventException
)

Remove a connection from the managed list.

Calling detach with an unmanaged connection won't do anything.

Detaching from the wrong listener will result in an WrongParentListener exception.

You can't call detach while the listener is runing. If you do so, it will throw a EventListenerRunning exception.

Parameters
[in]connectionThe connection to detach.
void SedNL::EventListener::join ( )

Join the EventListener thread.

When you call join, you ask the EventListener to stop processing events.

When join() is called, The EventListener close all the internal connections. Then, it join each consumer. When all consumer are stoped, the join function return. It means that each disconnected event will be processed.

Slot< Connection & > & SedNL::EventListener::on_connect ( )
inline

Bind the connect event.

Callback prototype : void my_on_connect(Connection&);

The connect event is guaranted to be processed imediately when a connection is received from the server.

Since the callback is executed in the listener thread, you would like to keep it small and fast.

Definition at line 28 of file EventListener.ipp.

void SedNL::EventListener::run ( )
throw (EventException
)

Launch the EventListener thread.

EventListener::run() launch a new thread and start listening to incoming events from TCPConnection, Connection and TCPServer.

If a new connection occure from TCPServer, a new Connection is created and added into the connection list.

The EventListener will take care of the memory allocated by new connections, and memory desalocation.

If more than one attached consumer bind the same event, then it will throw a EventCollision exception at startup.

To stop the listener, call join().


The documentation for this class was generated from the following files: