1 /*******************************************************************************
2   copyright:   Copyright (c) 2006 Juan Jose Comellas. All rights reserved
3   license:     BSD style: $(LICENSE)
4   author:      Juan Jose Comellas $(EMAIL juanjo@comellas.com.ar)
5 *******************************************************************************/
6 
7 module tango.io.selector.Selector;
8 
9 
10 
11 /**
12  * A multiplexor of conduit I/O events.
13  *
14  * A Selector can wait for I/O events (Read, Write, etc.) for multiple
15  * conduits efficiently (i.e. without consuming CPU cycles).
16  *
17  * The Selector is an alias for your system's most efficient I/O multiplexor,
18  * which will be determined during compilation.
19  *
20  * To create a Selector you need to use the open() method and when you decide
21  * you no longer need it you should call its close() method to free any system
22  * resources it may be consuming. All selectors that need to free resources
23  * when close() is called also implement a destructor that automatically calls
24  * this method. This means that if you declare your selector instance with the
25  * 'auto' keyword you won't have to worry about doing it manually.
26  *
27  * Once you have open()'ed your selector you need to associate the conduits to
28  * it by using the register() method. This method receives the conduit and the
29  * events you want to track for it. For example, if you wanted to read from
30  * the conduit you would do:
31  *
32  * ---
33  * selector.register(conduit, Event.Read, myObject);
34  * ---
35  *
36  * This method also accepts an optional third parameter to associate a
37  * user-defined object to the conduit. These three parameters together define
38  * a SelectionKey, which is what you'll receive when the conduit is "selected"
39  * (i.e. receives an event).
40  *
41  * If you need to modify your conduit's registration you need to use the
42  * reregister() method, which works like register(), but expects to be passed
43  * a conduit that has already been associated to the selector:
44  *
45  * ---
46  * selector.reregister(conduit, Event.Write, myObject);
47  * ---
48  *
49  * If you need to remove a conduit from the selector you do it by calling
50  * unregister():
51  *
52  * ---
53  * selector.unregister(conduit);
54  * ---
55  *
56  * Once you are done setting up the conduits you will want to wait for I/O
57  * events for them. To do that you need to use the select() method. This
58  * method blocks until either one of the conduits is selected or the
59  * specified timeout is reached. Even though it has two different versions:
60  * a) select(); b) select(Interval); the first one is just the same as doing
61  * select(Interval.max). In that case we don't have a timeout and
62  * select() blocks until a conduit receives an event.
63  *
64  * When select() returns you will receive an integer; if this integer is
65  * bigger than 0, it indicates the number of conduits that have been selected.
66  * If this number is 0, the it means that the selector reached a timeout, and
67  * if it's -1, then it means that there was an error. A normal block that deals 
68  * with the selection process would look like this:
69  *
70  * ---
71  * try
72  * {
73  *     int eventCount = selector.select(10.0);
74  *     if (eventCount > 0)
75  *     {
76  *         // Process the I/O events in the selected set
77  *     }
78  *     else if (eventCount == 0)
79  *     {
80  *         // Timeout
81  *     }
82  *     else if (eventCount == -1)
83  *     {
84  *         // Error
85  *     }
86  *     else
87  *     {
88  *         // Error: should never happen.
89  *     }
90  * }
91  * catch (SelectorException e)
92  * {
93  *     Stdout.format("Exception caught: {0}", e.toString()).newline();
94  * }
95  * ---
96  *
97  * Finally, to gather the events you need to iterate over the selector's
98  * selection set, which can be accessed via the selectedSet() method.
99  *
100  * ---
101  * foreach (SelectionKey key; selector.selectedSet())
102  * {
103  *     if (key.isReadable())
104  *     {
105  *         // Read from conduit
106  *         // [...]
107  *         // Then register it for writing
108  *         selector.reregister(key.conduit, Event.Write, key.attachment);
109  *     }
110  *
111  *     if (key.isWriteable())
112  *     {
113  *         // Write to conduit
114  *         // [...]
115  *         // Then register it for reading
116  *         selector.reregister(key.conduit, Event.Read, key.attachment);
117  *     }
118  *
119  *     if (key.isError())
120  *     {
121  *         // Problem with conduit; remove it from selector
122  *         selector.remove(conduit);
123  *     }
124  * }
125  * ---
126  */
127 version (linux)
128 {
129     public import tango.io.selector.EpollSelector;
130 
131     /**
132      * Default Selector for Linux.
133      */
134     alias EpollSelector Selector;
135 }
136 else version(Posix)
137 {
138     public import tango.io.selector.PollSelector;
139 
140     /**
141      * Default Selector for POSIX-compatible platforms.
142      */
143     alias PollSelector Selector;
144 }
145 else
146 {
147     public import tango.io.selector.SelectSelector;
148 
149     /**
150      * Default Selector for Windows.
151      */
152     alias SelectSelector Selector;
153 }