Tamer
C++ language extensions for event-driven programming
Loading...
Searching...
No Matches
dinternal.hh
1#ifndef TAMER_DINTERNAL_HH
2#define TAMER_DINTERNAL_HH 1
3#include <tamer/event.hh>
4#include <tamer/driver.hh>
5#include <sys/types.h>
6#include <string.h>
7namespace tamer {
8namespace tamerpriv {
9
10template <typename T>
11struct driver_fd : public T {
12 event<int> e[3];
13 int next_changedfd1;
14
15 template <typename O> inline driver_fd(O owner, int fd);
16 inline bool empty() const;
17 inline void clear();
18};
19
20template <typename T>
21struct driver_fdset {
22 inline driver_fdset();
23 inline ~driver_fdset();
24
25 template <typename O> inline void expand(O owner, int need_fd);
26 inline void push_change(int fd);
27 inline int pop_change();
28 inline bool has_change() const;
29
30 inline int size() const;
31 inline const driver_fd<T>& operator[](int fd) const;
32 inline driver_fd<T>& operator[](int fd);
33
34 private:
35 enum { fdblksiz = 256 };
36 driver_fd<T>** fdblk_;
37 driver_fd<T>* fdblk0_;
38 unsigned nfds_ = 0;
39 unsigned fdcap_ = fdblksiz;
40 unsigned changedfd1_ = 0;
41 struct alignas(driver_fd<T>) dfdspace {
42 unsigned char padding[sizeof(driver_fd<T>)];
43 };
44 dfdspace fdspace_[fdblksiz];
45
46 inline driver_fd<T>& at(unsigned fd);
47 inline const driver_fd<T>& at(unsigned fd) const;
48 template <typename O> void hard_expand(O owner, int need_fd);
49};
50
51struct driver_asapset {
52 inline ~driver_asapset();
53
54 inline bool empty() const;
55 inline void push(simple_event* se);
56 inline void pop_trigger();
57 void clear();
58
59 private:
60 simple_event** ses_ = nullptr;
61 unsigned head_ = 0;
62 unsigned tail_ = 0;
63 unsigned capmask_ = ~0U;
64
65 void expand();
66};
67
68struct driver_timerset {
69 inline ~driver_timerset();
70
71 inline bool empty() const;
72 inline bool has_foreground() const;
73 inline const timeval& expiry() const;
74 inline void cull();
75 void push(timeval when, simple_event* se, bool bg);
76 inline void pop_trigger();
77 void clear();
78
79 void check();
80
81 private:
82 struct trec {
83 timeval when;
84 unsigned order;
85 simple_event* se;
86 inline bool operator<(const trec &x) const;
87 inline void clean();
88 };
89
90 enum { arity = 4 };
91 trec* ts_ = nullptr;
92 mutable unsigned nts_ = 0;
93 mutable unsigned nfg_ = 0;
94 unsigned rand_ = 8173;
95 unsigned tcap_ = 0;
96 unsigned order_ = 0;
97
98 static inline unsigned heap_parent(unsigned i);
99 static inline unsigned heap_first_child(unsigned i);
100 inline unsigned heap_last_child(unsigned i) const;
101 void hard_cull(unsigned pos) const;
102 void expand();
103};
104
105
106template <typename T> template <typename O>
107inline driver_fd<T>::driver_fd(O owner, int fd)
108 : T(owner, fd), next_changedfd1(0) {
109}
110
111template <typename T>
112inline bool driver_fd<T>::empty() const {
113 return e[0].empty() && e[1].empty() && e[2].empty();
114}
115
116template <typename T>
117inline void driver_fd<T>::clear() {
118 e[0].trigger(outcome::destroy);
119 e[1].trigger(outcome::destroy);
120 e[2].trigger(outcome::destroy);
121}
122
123template <typename T>
124inline driver_fd<T>& driver_fdset<T>::at(unsigned fd) {
125 return fdblk_[fd / fdblksiz][fd % fdblksiz];
126}
127
128template <typename T>
129inline const driver_fd<T>& driver_fdset<T>::at(unsigned fd) const {
130 return fdblk_[fd / fdblksiz][fd % fdblksiz];
131}
132
133template <typename T>
134inline driver_fdset<T>::driver_fdset()
135 : fdblk_(&fdblk0_), fdblk0_(reinterpret_cast<driver_fd<T>*>(fdspace_)) {
136}
137
138template <typename T>
139inline driver_fdset<T>::~driver_fdset() {
140 for (unsigned i = 0; i < nfds_; ++i) {
141 at(i).~driver_fd<T>();
142 }
143 for (unsigned i = 1; i < fdcap_ / fdblksiz; ++i) {
144 delete[] reinterpret_cast<dfdspace*>(fdblk_[i]);
145 }
146 if (fdcap_ > fdblksiz) {
147 delete[] fdblk_;
148 }
149}
150
151template <typename T> template <typename O>
152void driver_fdset<T>::expand(O owner, int need_fd) {
153 if (need_fd >= (int) nfds_) {
154 hard_expand(owner, need_fd);
155 }
156}
157
158template <typename T> template <typename O>
159void driver_fdset<T>::hard_expand(O owner, int need_fd) {
160 if (need_fd >= (int) fdcap_) {
161 unsigned newfdcap = (need_fd | (fdblksiz - 1)) + 1;
162 driver_fd<T>** newfdblk = new driver_fd<T>*[newfdcap / fdblksiz];
163 for (unsigned i = 0; i < newfdcap / fdblksiz; ++i) {
164 if (i < fdcap_ / fdblksiz) {
165 newfdblk[i] = fdblk_[i];
166 } else {
167 newfdblk[i] = reinterpret_cast<driver_fd<T>*>(new dfdspace[fdblksiz]);
168 }
169 }
170 if (fdcap_ > fdblksiz) {
171 delete[] fdblk_;
172 }
173 fdblk_ = newfdblk;
174 fdcap_ = newfdcap;
175 }
176
177 while (need_fd >= (int) nfds_) {
178 new((void*) &at(nfds_)) driver_fd<T>(owner, nfds_);
179 ++nfds_;
180 }
181}
182
183template <typename T>
184inline bool driver_fdset<T>::has_change() const {
185 return changedfd1_ != 0;
186}
187
188template <typename T>
189inline void driver_fdset<T>::push_change(int fd) {
190 assert(fd >= 0 && (unsigned) fd < nfds_);
191 if (at(fd).next_changedfd1 == 0) {
192 at(fd).next_changedfd1 = changedfd1_;
193 changedfd1_ = fd + 1;
194 }
195}
196
197template <typename T>
198inline int driver_fdset<T>::pop_change() {
199 int fd = changedfd1_ - 1;
200 if (fd >= 0) {
201 changedfd1_ = at(fd).next_changedfd1;
202 at(fd).next_changedfd1 = 0;
203 }
204 return fd;
205}
206
207template <typename T>
208inline int driver_fdset<T>::size() const {
209 return nfds_;
210}
211
212template <typename T>
213inline const driver_fd<T>& driver_fdset<T>::operator[](int fd) const {
214 assert((unsigned) fd < nfds_);
215 return at(fd);
216}
217
218template <typename T>
219inline driver_fd<T>& driver_fdset<T>::operator[](int fd) {
220 assert((unsigned) fd < nfds_);
221 return at(fd);
222}
223
224inline void* make_fd_callback(const driver* d, int fd) {
225 uintptr_t x = d->index() + fd * driver::capacity;
226 return reinterpret_cast<void*>(x);
227}
228
229inline driver* fd_callback_driver(void* callback) {
230 uintptr_t x = reinterpret_cast<uintptr_t>(callback);
231 return driver::by_index(x % driver::capacity);
232}
233
234inline int fd_callback_fd(void* callback) {
235 uintptr_t x = reinterpret_cast<uintptr_t>(callback);
236 return x / driver::capacity;
237}
238
239inline driver_asapset::~driver_asapset() {
240 clear();
241 delete[] ses_;
242}
243
244inline bool driver_asapset::empty() const {
245 return head_ == tail_;
246}
247
248inline void driver_asapset::push(simple_event *se) {
249 if (tail_ - head_ == capmask_ + 1) {
250 expand();
251 }
252 ses_[tail_ & capmask_] = se;
253 ++tail_;
254}
255
256inline void driver_asapset::pop_trigger() {
257 assert(head_ != tail_);
258 simple_event* se = ses_[head_ & capmask_];
259 ++head_;
260 se->simple_trigger(false);
261}
262
263inline driver_timerset::~driver_timerset() {
264 clear();
265 delete[] ts_;
266}
267
268inline bool driver_timerset::empty() const {
269 return nts_ == 0;
270}
271
272inline bool driver_timerset::has_foreground() const {
273 return nfg_ != 0;
274}
275
276inline const timeval &driver_timerset::expiry() const {
277 assert(nts_ != 0);
278 return ts_[0].when;
279}
280
281inline void driver_timerset::cull() {
282 while (nts_ != 0 && ts_[0].se->empty()) {
283 hard_cull(0);
284 }
285}
286
287inline bool driver_timerset::trec::operator<(const trec &x) const {
288 return when.tv_sec < x.when.tv_sec
289 || (when.tv_sec == x.when.tv_sec
290 && (when.tv_usec < x.when.tv_usec
291 || (when.tv_usec == x.when.tv_usec
292 && (int) (order - x.order) < 0)));
293}
294
295inline void driver_timerset::trec::clean() {
296 simple_event::unuse_clean(se);
297}
298
299inline unsigned driver_timerset::heap_parent(unsigned i) {
300 return (i - (arity == 2)) / arity;
301}
302
303inline unsigned driver_timerset::heap_first_child(unsigned i) {
304 return i * arity + (arity == 2 || i == 0);
305}
306
307inline unsigned driver_timerset::heap_last_child(unsigned i) const {
308 unsigned p = i * arity + arity + (arity == 2);
309 return p < nts_ ? p : nts_;
310}
311
312inline void driver_timerset::pop_trigger() {
313 hard_cull((unsigned) -1);
314}
315
316} // namespace tamerpriv
317} // namespace tamer
318#endif
Functions for registering primitive events and managing the event loop.
The event template classes and helper functions.
Namespace containing public Tamer classes and functions for the Tamer core.
Definition adapter.hh:17