A selector is a multiplexor for I/O events associated to a Conduit.
All selectors must implement this interface.
A selector needs to be initialized by calling the open() method to pass
it the initial amount of conduits that it will handle and the maximum
amount of events that will be returned per call to select(). In both cases,
these values are only hints and may not even be used by the specific
ISelector implementation you choose to use, so you cannot make any
assumptions regarding what results from the call to select() (i.e. you
may receive more or less events per call to select() than what was passed
in the 'maxEvents' argument. The amount of conduits that the selector can
manage will be incremented dynamically if necessary.
To add or modify conduit registrations in the selector, use the register()
method. To remove conduit registrations from the selector, use the
unregister() method.
To wait for events from the conduits you need to call any of the select()
methods. The selector cannot be modified from another thread while
blocking on a call to these methods.
Once the selector is no longer used you must call the close() method so
that the selector can free any resources it may have allocated in the call
to open().
Examples:
import tango.io.selector.model.ISelector;
import tango.io.SocketConduit;
import tango.io.Stdout;
ISelector selector;
SocketConduit conduit1;
SocketConduit conduit2;
MyClass object1;
MyClass object2;
int eventCount;
// Initialize the selector assuming that it will deal with 2 conduits and
// will receive 2 events per invocation to the select() method.
selector.open(2, 2);
selector.register(conduit, Event.Read, object1);
selector.register(conduit, Event.Write, object2);
eventCount = selector.select();
if (eventCount > 0)
{
char[16] buffer;
int count;
foreach (SelectionKey key, selector.selectedSet())
{
if (key.isReadable())
{
count = (cast(SocketConduit) key.conduit).read(buffer);
if (count != IConduit.Eof)
{
Stdout.format("Received '{0}' from peer\n", buffer[0..count]);
selector.register(key.conduit, Event.Write, key.attachment);
}
else
{
selector.unregister(key.conduit);
key.conduit.close();
}
}
if (key.isWritable())
{
count = (cast(SocketConduit) key.conduit).write("MESSAGE");
if (count != IConduit.Eof)
{
Stdout.print("Sent 'MESSAGE' to peer\n");
selector.register(key.conduit, Event.Read, key.attachment);
}
else
{
selector.unregister(key.conduit);
key.conduit.close();
}
}
if (key.isError() || key.isHangup() || key.isInvalidHandle())
{
selector.unregister(key.conduit);
key.conduit.close();
}
}
}
selector.close();
- abstract void open(uint size, uint maxEvents);
- Initialize the selector.
Params:
uint size |
value that provides a hint for the maximum amount of
conduits that will be registered |
uint maxEvents |
value that provides a hint for the maximum amount of
conduit events that will be returned in the selection
set per call to select. |
- abstract void close();
- Free any operating system resources that may have been allocated in the
call to open().
Remarks:
Not all of the selectors need to free resources other than allocated
memory, but those that do will normally also add a call to close() in
their destructors.
- abstract void register(ISelectable conduit, Event events, Object attachment = null);
- Associate a conduit to the selector and track specific I/O events.
If the conduit is already part of the selector, modify the events or
atachment.
Params:
ISelectable conduit |
conduit that will be associated to the selector;
must be a valid conduit (i.e. not null and open). |
Event events |
bit mask of Event values that represent the events that
will be tracked for the conduit. |
Object attachment |
optional object with application-specific data that will
be available when an event is triggered for the conduit |
Examples:
ISelector selector;
SocketConduit conduit;
MyClass object;
selector.register(conduit, Event.Read | Event.Write, object);
- deprecated abstract void reregister(ISelectable conduit, Event events, Object attachment = null);
- Deprecated, use register instead
- abstract void unregister(ISelectable conduit);
- Remove a conduit from the selector.
Params:
ISelectable conduit |
conduit that had been previously associated to the
selector; it can be null. |
Remarks:
Unregistering a null conduit is allowed and no exception is thrown
if this happens.
- abstract int select();
- Wait indefinitely for I/O events from the registered conduits.
Returns:
The amount of conduits that have received events; 0 if no conduits
have received events within the specified timeout and -1 if there
was an error.
- abstract int select(TimeSpan timeout);
- Wait for I/O events from the registered conduits for a specified
amount of time.
Params:
TimeSpan timeout |
TimeSpan with the maximum amount of time that the
selector will wait for events from the conduits; the
amount of time is relative to the current system time
(i.e. just the number of milliseconds that the selector
has to wait for the events). |
Returns:
The amount of conduits that have received events; 0 if no conduits
have received events within the specified timeout.
- abstract int select(double timeout);
- Wait for I/O events from the registered conduits for a specified
amount of time.
Note:
This representation of timeout is not always accurate, so it is
possible that the function will return with a timeout before the
specified period. For more accuracy, use the TimeSpan version.
Note:
Implementers should define this method as:
select(TimeSpan.interval(timeout));
Params:
double timeout |
the maximum amount of time in seconds that the
selector will wait for events from the conduits; the
amount of time is relative to the current system time
(i.e. just the number of milliseconds that the selector
has to wait for the events). |
Returns:
The amount of conduits that have received events; 0 if no conduits
have received events within the specified timeout.
- abstract ISelectionSet selectedSet();
- Return the selection set resulting from the call to any of the select()
methods.
Remarks:
If the call to select() was unsuccessful or it did not return any
events, the returned value will be null.
- abstract SelectionKey key(ISelectable conduit);
- Return the selection key resulting from the registration of a conduit
to the selector.
Remarks:
If the conduit is not registered to the selector the returned
value will SelectionKey.init. No exception will be thrown by this
method.
- abstract int opApply(scope int delegate(ref SelectionKey sk) dg);
- Iterate through the currently registered selection keys. Note that you
should not erase or add any items from the selector while iterating,
although you can register existing conduits again.