root/trunk/whisperlib/net/base/selector.h

Revision 7, 7.2 kB (checked in by whispercastorg, 2 years ago)

version 0.2.0

Line 
1 // Copyright (c) 2009, Whispersoft s.r.l.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 // * Neither the name of Whispersoft s.r.l. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 //
30 // Authors: Cosmin Tudorache & Catalin Popescu
31
32 #ifndef __NET_BASE_SELECTOR_H__
33 #define __NET_BASE_SELECTOR_H__
34
35 #include <sys/epoll.h>
36 #include <sys/types.h>
37 #include <list>
38 #include <deque>
39 #include <set>
40 #include <map>
41
42 #include <whisperlib/common/base/types.h>
43 #include WHISPER_HASH_MAP_HEADER
44
45 #include <whisperlib/common/base/callback.h>
46 #include <whisperlib/common/sync/mutex.h>
47 #include <whisperlib/common/sync/thread.h>
48
49 // This, it seems, is not defined in our standard includes
50 #ifndef EPOLLRDHUP
51 #define EPOLLRDHUP 0x2000
52 #endif
53
54 // Just a helper function
55
56 namespace net {
57
58 class Selectable;
59
60 //
61 // Magic arround an epoll -
62 //
63 // //////////////////
64 //
65 // NOTE:  IT IS THREAD-UNSAFE - except where noted
66 //
67 //
68 class Selector {
69  public:
70   Selector();
71   ~Selector();
72
73   // Register an I/O object for read/write/error event callbacks. By default:
74   //  - read callback is enabled.
75   //  - write callback is disabled.
76   //  - error callback is enabled.
77   // returns:
78   //   success status.
79   bool Register(Selectable* s);
80
81   // Unregister a previously registered I/O object.
82   //  s - the selectable object to be unregistered
83   void Unregister(Selectable* s);
84
85   // Enable/disable a certain event callback for the given selectable
86   // -- Call this only from the select loop
87   void EnableWriteCallback(Selectable* s, bool enable) {
88     UpdateDesire(s, enable, kWantWrite);
89   }
90   void EnableReadCallback(Selectable* s, bool enable) {
91     UpdateDesire(s, enable, kWantRead);
92   }
93
94   // Runs the main select loop
95   void Loop();
96
97   // Makes an exit from the select loop
98   void MakeLoopExit();
99   // Returns true if the selector is no longer in the loop (though
100   // registered callbacks can still execute !!)
101   bool IsExiting() const {
102     return should_end_;
103   }
104
105   // Returns true if this call was made from the select server thread
106   bool IsInSelectThread() const;
107
108   //
109   // Runs this closure in the select loop
110   // - THIS IS SAFE TO CALL FROM ANOTHER THREAD -
111   // NOTE: It is legal to add closures while the selector is shutting down..
112   //       (i.e. IsExiting() == true)
113   //
114  private:
115   template <typename T> static void GeneralAsynchronousDelete(T* ob) {
116     delete ob;
117   }
118  public:
119   bool RunInSelectLoop(Closure* callback);
120   template <typename T> bool DeleteInSelectLoop(T* ob) {
121     return RunInSelectLoop(
122         NewCallback(&Selector::GeneralAsynchronousDelete<T>, ob));
123   }
124
125   // Functions for running in the select loop the given Closure after
126   // a specified time interval
127
128   // -- THESE ARE NOT THREAD SAFE --
129
130   // Registers the given callback to be run after timeout_in_ms miliseconds.
131   // Returns the ticks in ms when the callback will be run
132   int64 RegisterAlarm(Closure* callback, int64 timeout_in_ms);
133   // Cancels a previously registered alarm. Returns if the callback was found
134   // as registered.
135   bool UnregisterAlarm(Closure* callback);
136   // Changes the timeout for the given callback to timeout_in_ms from *this*
137   // moment.
138   bool ReregisterAlarm(Closure* callback, int64 timeout_in_ms);
139
140   // The current moment when the select loop was broken:
141   int64 now() const { return now_; }
142
143   // Desires of selectables
144   static const int32 kWantRead  = 1;
145   static const int32 kWantWrite = 2;
146   static const int32 kWantError = 4;
147  private:
148   //  add a file descriptor in the epoll, and link to the given data pointer.
149   bool EpollCtlAdd(int fd, void* user_data, int event);
150   //  remove a file descriptor from the epoll
151   bool EpollCtlDel(int fd);
152
153   // helper that turns on/off fd desires in the assoiciated RegistrationData
154   void UpdateDesire(Selectable* s, bool enable, int32 desire);
155
156   // Cleans and closes the entire list of selectable objects
157   void CleanAndCloseAll();
158
159   // This runs all the functions from to_run_ (if any)
160   void RunAllClosures();
161
162   // This writes a byte in the internal pipe in order to make the
163   // select loop wake up
164   void SendWakeSignal();
165
166   pthread_t tid_;       // selector's internal thread id
167   bool should_end_;     // a make loop exit was called
168   int epfd_;            // epoll file descriptor
169
170   typedef set<Selectable*> SelectableSet;
171   typedef list<Selectable*> SelectableList;
172   // typedef multimap<int64, Closure*> AlarmsMap;
173   typedef set< pair<int64, Closure*> > AlarmsSet;
174   typedef hash_map<Closure*, int64> ReverseAlarmsMap;
175
176   SelectableSet registered_;   // the set of registered I/O objects
177   AlarmsSet alarms_;           // the registered alarms..
178   ReverseAlarmsMap reverse_alarms_;
179   // this maps from alarm to wake up time
180   // -> allows us to change the deadline for
181   // an alarm
182
183   synch::Mutex mutex_;         // mutex that guards the access to
184   // internal control stuff
185   int signal_pipe_[2];         // these two file descriptors are for waking the
186   // selector when a function needs to be executed
187   // in the select loop
188   deque<Closure*> to_run_;     // functions registered to be run in the select
189   // loop
190
191   int64           now_;        // the time of the last cycle exit
192   // we wake up from the loop every 100 ms by default
193   static const int32 kStandardWakeUpTimeMs = 100;
194
195   DISALLOW_EVIL_CONSTRUCTORS(Selector);
196 };
197
198 class SelectorThread {
199  public:
200   SelectorThread()
201       : thread_(NewCallback(this, &SelectorThread::Execution)) {
202   }
203   ~SelectorThread() {
204     selector_.RunInSelectLoop(NewCallback(&selector_,
205                                           &net::Selector::MakeLoopExit));
206     thread_.Join();
207   }
208   void Start() {
209     CHECK(thread_.SetJoinable());
210     CHECK(thread_.Start());
211   }
212
213   const Selector* selector() const {
214     return &selector_;
215   }
216   Selector* mutable_selector() {
217     return &selector_;
218   }
219
220  private:
221   void Execution() {
222     selector_.Loop();
223   }
224   thread::Thread thread_;
225   Selector selector_;
226
227   DISALLOW_EVIL_CONSTRUCTORS(SelectorThread);
228 };
229 }
230 #endif  // __NET_BASE_SELECTOR__
Note: See TracBrowser for help on using the browser.