1 /*******************************************************************************
2 
3     Classes used by the EpollSelectDispatcher to manage the set of registered
4     clients.
5 
6     Copyright:
7         Copyright (c) 2009-2016 dunnhumby Germany GmbH.
8         All rights reserved.
9 
10     License:
11         Boost Software License Version 1.0. See LICENSE_BOOST.txt for details.
12         Alternatively, this file may be distributed under the terms of the Tango
13         3-Clause BSD License (see LICENSE_BSD.txt for details).
14 
15 *******************************************************************************/
16 
17 module ocean.io.select.selector.RegisteredClients;
18 
19 
20 
21 
22 import ocean.io.select.client.model.ISelectClient;
23 
24 import ocean.util.container.map.Set;
25 
26 debug ( ISelectClient ) import ocean.io.Stdout : Stderr;
27 
28 
29 
30 
31 /*******************************************************************************
32 
33     Base class for a set of registered clients, with methods to add & remove
34     clients, and to tell how many clients are currently registered. When a
35     client is added or removed from the set its registered() or
36     unergistered() method, respectively, is called automatically.
37 
38 *******************************************************************************/
39 
40 public abstract class IRegisteredClients
41 {
42     /***************************************************************************
43 
44         Adds a client to the set of registered clients. Calls the client's
45         registered() method, then calls the abstract add_() method.
46 
47         Params:
48             client = client to add
49 
50     ***************************************************************************/
51 
52     final public void opOpAssign ( string op : "+" ) ( ISelectClient client )
53     {
54         debug ( ISelectClient ) Stderr.formatln("{} :: Registered", client).flush();
55         client.registered();
56         this.add_(client);
57     }
58 
59     abstract protected void add_ ( ISelectClient client );
60 
61     /***************************************************************************
62 
63         Removes a client from the set of registered clients. Calls the client's
64         unregistered() method, then calls the abstract remove_() method.
65 
66         Params:
67             client = client to remove
68 
69     ***************************************************************************/
70 
71     final public void opOpAssign ( string op : "-" ) ( ISelectClient client )
72     {
73         debug ( ISelectClient ) Stderr.formatln("{} :: Unregistered", client).flush();
74         client.unregistered();
75         this.remove_(client);
76     }
77 
78     abstract protected void remove_ ( ISelectClient client );
79 
80     /***************************************************************************
81 
82         Returns:
83             the number of clients currently registered
84 
85     ***************************************************************************/
86 
87     abstract public size_t length ( );
88 }
89 
90 
91 /*******************************************************************************
92 
93     Class to keep track of how many clients are registered.
94 
95 *******************************************************************************/
96 
97 public final class ClientCount : IRegisteredClients
98 {
99     /***************************************************************************
100 
101         Number of clients registered.
102 
103     ***************************************************************************/
104 
105     private size_t count;
106 
107     /***************************************************************************
108 
109         Adds a client to the set.
110 
111         Params:
112             c = client to add
113 
114     ***************************************************************************/
115 
116     protected override void add_ ( ISelectClient c )
117     {
118         this.count++;
119     }
120 
121     /***************************************************************************
122 
123         Removes a client from the set.
124 
125         Params:
126             c = client to remove
127 
128     ***************************************************************************/
129 
130     protected override void remove_ ( ISelectClient c )
131     {
132         this.count--;
133     }
134 
135     /***************************************************************************
136 
137         Returns:
138             the number of clients currently registered
139 
140     ***************************************************************************/
141 
142     public override size_t length ( )
143     {
144         return this.count;
145     }
146 }
147 
148 
149 /*******************************************************************************
150 
151     Class to keep track of a set of registered clients, including the
152     capacity to iterate over them. This class is used only in debug builds,
153     where it is useful to be able to tell exactly which clients are registered.
154 
155 *******************************************************************************/
156 
157 public final class ClientSet : IRegisteredClients
158 {
159     /***************************************************************************
160 
161         Set of clients.
162 
163     ***************************************************************************/
164 
165     static private class Clients : Set!(ISelectClient)
166     {
167         /***********************************************************************
168 
169             Estimated maximum number of clients, used by the super class to
170             determine the number of buckets in the set.
171 
172         ***********************************************************************/
173 
174         static immutable max_clients_estimate = 1000;
175 
176         /***********************************************************************
177 
178             Private constructor, prevents instantiation from the outside.
179 
180         ***********************************************************************/
181 
182         private this ( )
183         {
184             super(this.max_clients_estimate);
185         }
186 
187         /***********************************************************************
188 
189             Hashing function, required by super class. Determines which set
190             bucket is responsible for the specified client.
191 
192             Params:
193                 c = client to get hash for
194 
195             Returns:
196                 hash for client (the class reference is used)
197 
198         ***********************************************************************/
199 
200         public override hash_t toHash ( in ISelectClient c )
201         {
202             return cast(hash_t)cast(void*)c;
203         }
204     }
205 
206     private Clients clients;
207 
208     /***************************************************************************
209 
210         Constructor.
211 
212     ***************************************************************************/
213 
214     public this ( )
215     {
216         this.clients = new Clients;
217     }
218 
219     /***************************************************************************
220 
221         Adds a client to the set.
222 
223         Params:
224             c = client to add
225 
226     ***************************************************************************/
227 
228     public override void add_ ( ISelectClient c )
229     {
230         this.clients.put(c);
231     }
232 
233     /***************************************************************************
234 
235         Removes a client from the set.
236 
237         Params:
238             c = client to remove
239 
240     ***************************************************************************/
241 
242     public override void remove_ ( ISelectClient c )
243     {
244         this.clients.remove(c);
245     }
246 
247     /***************************************************************************
248 
249         Returns:
250             the number of clients currently registered
251 
252     ***************************************************************************/
253 
254     public override size_t length ( )
255     {
256         return this.clients.bucket_info.length;
257     }
258 
259     /***************************************************************************
260 
261         foreach operator over registered clients.
262 
263     ***************************************************************************/
264 
265     public int opApply ( scope int delegate ( ref ISelectClient ) dg )
266     {
267         int res;
268         foreach ( client; this.clients )
269         {
270             res = dg(client);
271             if ( res ) break;
272         }
273         return res;
274     }
275 }
276