- eConnections holds reference to object
[enigma2.git] / lib / base / ebase.h
1 #ifndef __ebase_h
2 #define __ebase_h
3
4 #include <vector>
5 #include <map>
6 #include <sys/poll.h>
7 #include <sys/time.h>
8 #include <asm/types.h>
9 #include <time.h>
10
11 #include <lib/base/eptrlist.h>
12 #include <libsig_comp.h>
13
14 class eApplication;
15
16 extern eApplication* eApp;
17
18 static inline bool operator<( const timeval &t1, const timeval &t2 )
19 {
20         return t1.tv_sec < t2.tv_sec || (t1.tv_sec == t2.tv_sec && t1.tv_usec < t2.tv_usec);
21 }
22
23 static inline timeval &operator+=( timeval &t1, const timeval &t2 )
24 {
25         t1.tv_sec += t2.tv_sec;
26         if ( (t1.tv_usec += t2.tv_usec) >= 1000000 )
27         {
28                 t1.tv_sec++;
29                 t1.tv_usec -= 1000000;
30         }
31         return t1;
32 }
33
34 static inline timeval operator+( const timeval &t1, const timeval &t2 )
35 {
36         timeval tmp;
37         tmp.tv_sec = t1.tv_sec + t2.tv_sec;
38         if ( (tmp.tv_usec = t1.tv_usec + t2.tv_usec) >= 1000000 )
39         {
40                 tmp.tv_sec++;
41                 tmp.tv_usec -= 1000000;
42         }
43         return tmp;
44 }
45
46 static inline timeval operator-( const timeval &t1, const timeval &t2 )
47 {
48         timeval tmp;
49         tmp.tv_sec = t1.tv_sec - t2.tv_sec;
50         if ( (tmp.tv_usec = t1.tv_usec - t2.tv_usec) < 0 )
51         {
52                 tmp.tv_sec--;
53                 tmp.tv_usec += 1000000;
54         }
55         return tmp;
56 }
57
58 static inline timeval operator-=( timeval &t1, const timeval &t2 )
59 {
60         t1.tv_sec -= t2.tv_sec;
61         if ( (t1.tv_usec -= t2.tv_usec) < 0 )
62         {
63                 t1.tv_sec--;
64                 t1.tv_usec += 1000000;
65         }
66         return t1;
67 }
68
69 static inline timeval &operator+=( timeval &t1, const long msek )
70 {
71         t1.tv_sec += msek / 1000;
72         if ( (t1.tv_usec += (msek % 1000) * 1000) >= 1000000 )
73         {
74                 t1.tv_sec++;
75                 t1.tv_usec -= 1000000;
76         }
77         return t1;
78 }
79
80 static inline timeval operator+( const timeval &t1, const long msek )
81 {
82         timeval tmp;
83         tmp.tv_sec = t1.tv_sec + msek / 1000;
84         if ( (tmp.tv_usec = t1.tv_usec + (msek % 1000) * 1000) >= 1000000 )
85         {
86                 tmp.tv_sec++;
87                 tmp.tv_usec -= 1000000;
88         }
89         return tmp;
90 }
91
92 static inline timeval operator-( const timeval &t1, const long msek )
93 {
94         timeval tmp;
95         tmp.tv_sec = t1.tv_sec - msek / 1000;
96         if ( (tmp.tv_usec = t1.tv_usec - (msek % 1000)*1000) < 0 )
97         {
98                 tmp.tv_sec--;
99                 tmp.tv_usec += 1000000;
100         }
101         return tmp;
102 }
103
104 static inline timeval operator-=( timeval &t1, const long msek )
105 {
106         t1.tv_sec -= msek / 1000;
107         if ( (t1.tv_usec -= (msek % 1000) * 1000) < 0 )
108         {
109                 t1.tv_sec--;
110                 t1.tv_usec += 1000000;
111         }
112         return t1;
113 }
114
115 static inline timeval timeout_timeval ( const timeval & orig )
116 {
117         timeval now;
118   gettimeofday(&now,0);
119
120         return orig-now;
121 }
122
123 static inline long timeout_usec ( const timeval & orig )
124 {
125         timeval now;
126   gettimeofday(&now,0);
127
128         return (orig-now).tv_sec*1000000 + (orig-now).tv_usec;
129 }
130
131 class eMainloop;
132
133                                         // die beiden signalquellen: SocketNotifier...
134
135 /**
136  * \brief Gives a callback when data on a file descriptor is ready.
137  *
138  * This class emits the signal \c eSocketNotifier::activate whenever the
139  * event specified by \c req is available.
140  */
141 class eSocketNotifier
142 {
143 public:
144         enum { Read=POLLIN, Write=POLLOUT, Priority=POLLPRI, Error=POLLERR, Hungup=POLLHUP };
145 private:
146         eMainloop &context;
147         int fd;
148         int state;
149         int requested;          // requested events (POLLIN, ...)
150 public:
151         /**
152          * \brief Constructs a eSocketNotifier.
153          * \param context The thread where to bind the socketnotifier to. The signal is emitted from that thread.
154          * \param fd The filedescriptor to monitor. Can be a device or a socket.
155          * \param req The events to watch to, normally either \c Read or \c Write. You can specify any events that \c poll supports.
156          * \param startnow Specifies if the socketnotifier should start immediately.
157          */
158         eSocketNotifier(eMainloop *context, int fd, int req, bool startnow=true);
159         ~eSocketNotifier();
160
161         Signal1<void, int> activated;
162         void activate(int what) { /*emit*/ activated(what); }
163
164         void start();
165         void stop();
166         bool isRunning() { return state; }
167
168         int getFD() { return fd; }
169         int getRequested() { return requested; }
170         void setRequested(int req) { requested=req; }
171 };
172
173                                 // ... und Timer
174 /**
175  * \brief Gives a callback after a specified timeout.
176  *
177  * This class emits the signal \c eTimer::timeout after the specified timeout.
178  */
179 class eTimer
180 {
181         eMainloop &context;
182         timeval nextActivation;
183         long interval;
184         bool bSingleShot;
185         bool bActive;
186 public:
187         /**
188          * \brief Constructs a timer.
189          *
190          * The timer is not yet active, it has to be started with \c start.
191          * \param context The thread from which the signal should be emitted.
192          */
193         eTimer(eMainloop *context): context(*context), bActive(false) { }
194         ~eTimer()       { if (bActive) stop(); }
195
196         Signal0<void> timeout;
197         void activate();
198
199         bool isActive() { return bActive; }
200         timeval &getNextActivation() { return nextActivation; }
201
202         void start(long msec, bool singleShot=false);
203         void stop();
204         void changeInterval(long msek);
205         bool operator<(const eTimer& t) const   {               return nextActivation < t.nextActivation;               }
206 };
207
208                         // werden in einer mainloop verarbeitet
209 class eMainloop
210 {
211         std::map<int, eSocketNotifier*> notifiers;
212         ePtrList<eTimer> TimerList;
213         bool app_exit_loop;
214         bool app_quit_now;
215         int loop_level;
216         void processOneEvent();
217         int retval;
218 public:
219         eMainloop():app_quit_now(0),loop_level(0),retval(0){    }
220         void addSocketNotifier(eSocketNotifier *sn);
221         void removeSocketNotifier(eSocketNotifier *sn);
222         void addTimer(eTimer* e)        {               TimerList.push_back(e);         TimerList.sort();       }
223         void removeTimer(eTimer* e)     {               TimerList.remove(e);    }
224
225         int looplevel() { return loop_level; }
226         
227         int exec();  // recursive enter the loop
228         void quit(int ret=0); // leave all pending loops (recursive leave())
229         void enter_loop();
230         void exit_loop();
231 };
232
233 /**
234  * \brief The application class.
235  *
236  * An application provides a mainloop, and runs in the primary thread.
237  * You can have other threads, too, but this is the primary one.
238  */
239 class eApplication: public eMainloop
240 {
241 public:
242         eApplication()
243         {
244                 if (!eApp)
245                         eApp = this;
246         }
247         ~eApplication()
248         {
249                 eApp = 0;
250         }
251 };
252 #endif