Skip to content

Commit 6f348af

Browse files
committed
feat: userspace eventloop abstraction on sockets
1 parent c711cc2 commit 6f348af

16 files changed

+847
-232
lines changed

include/ck/func.h

+45-39
Original file line numberDiff line numberDiff line change
@@ -5,52 +5,58 @@
55

66
namespace ck {
77

8-
template <typename T>
9-
class func;
10-
11-
template <typename Out, typename... In>
12-
class func<Out(In...)> {
13-
public:
14-
template <typename T>
15-
func& operator=(T t) {
16-
m_callable_wrapper = make_unique<CallableWrapper<T>>(move(t));
17-
return *this;
18-
}
19-
208
template <typename T>
21-
func(T &&t) {
22-
operator=(move(t));
23-
}
9+
class func;
2410

25-
Out operator()(In... args) const {
26-
assert(m_callable_wrapper);
27-
return m_callable_wrapper->call(args...);
28-
}
29-
30-
private:
31-
class CallableWrapperBase {
11+
template <typename Out, typename... In>
12+
class func<Out(In...)> {
3213
public:
33-
virtual ~CallableWrapperBase() {}
34-
virtual Out call(In...) const = 0;
35-
};
14+
template <typename T>
15+
func& operator=(T t) {
16+
m_callable_wrapper = make_unique<CallableWrapper<T>>(move(t));
17+
return *this;
18+
}
3619

37-
template <typename CallableType>
38-
class CallableWrapper final : public CallableWrapperBase {
39-
public:
40-
explicit CallableWrapper(CallableType&& callable)
41-
: m_callable(move(callable)) {}
20+
template <typename T>
21+
func(T&& t) {
22+
operator=(move(t));
23+
}
4224

43-
CallableWrapper(const CallableWrapper&) = delete;
44-
CallableWrapper& operator=(const CallableWrapper&) = delete;
25+
func(void) {
26+
m_callable_wrapper = nullptr;
27+
}
4528

46-
Out call(In... in) const final override {
47-
return m_callable(forward<In>(in)...);
29+
Out operator()(In... args) const {
30+
assert(m_callable_wrapper);
31+
return m_callable_wrapper->call(args...);
4832
}
4933

34+
operator bool(void) { return m_callable_wrapper.get() != NULL; }
35+
5036
private:
51-
CallableType m_callable;
37+
class CallableWrapperBase {
38+
public:
39+
virtual ~CallableWrapperBase() {}
40+
virtual Out call(In...) const = 0;
41+
};
42+
43+
template <typename CallableType>
44+
class CallableWrapper final : public CallableWrapperBase {
45+
public:
46+
explicit CallableWrapper(CallableType&& callable)
47+
: m_callable(move(callable)) {}
48+
49+
CallableWrapper(const CallableWrapper&) = delete;
50+
CallableWrapper& operator=(const CallableWrapper&) = delete;
51+
52+
Out call(In... in) const final override {
53+
return m_callable(forward<In>(in)...);
54+
}
55+
56+
private:
57+
CallableType m_callable;
58+
};
59+
60+
unique_ptr<CallableWrapperBase> m_callable_wrapper;
5261
};
53-
54-
unique_ptr<CallableWrapperBase> m_callable_wrapper;
55-
};
56-
}
62+
} // namespace ck

include/template_lib.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ DEF_INT_TRAITS(unsigned long);
4848
template <typename T>
4949
struct Traits<T*> {
5050
static unsigned hash(const T* p) {
51-
return (unsigned)p; // int_hash((unsigned)(__PTRDIFF_TYPE__)p);
51+
return (unsigned long long)p; // int_hash((unsigned)(__PTRDIFF_TYPE__)p);
5252
}
5353
static constexpr bool is_trivial() { return true; }
5454
static void dump(const T* p) { printk("%p", p); }

libc/src/ck/eventloop.cpp

+155
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
#include <ck/eventloop.h>
2+
#include <ck/fsnotifier.h>
3+
#include <ck/map.h>
4+
#include <stdio.h>
5+
#include <stdlib.h>
6+
#include <unistd.h>
7+
8+
#include <chariot/awaitfs_types.h>
9+
#include <sys/syscall.h>
10+
#include "ck/event.h"
11+
#include "ck/event.h"
12+
13+
static ck::HashTable<ck::fsnotifier *> s_notifiers;
14+
15+
ck::eventloop *active_eventloop = NULL;
16+
17+
ck::eventloop::eventloop(void) {
18+
/*
19+
if (active_eventloop != NULL) {
20+
panic(
21+
"Attempt to construct an event loop despite there already being one in "
22+
"existence\n");
23+
exit(EXIT_FAILURE);
24+
}
25+
active_eventloop = this;
26+
*/
27+
}
28+
29+
ck::eventloop::~eventloop(void) {
30+
/*
31+
active_eventloop = NULL;
32+
*/
33+
}
34+
35+
36+
37+
void ck::eventloop::start(void) {
38+
auto old = active_eventloop;
39+
active_eventloop = this;
40+
for (;;) {
41+
if (m_finished) break;
42+
pump();
43+
dispatch();
44+
}
45+
active_eventloop = old;
46+
}
47+
48+
49+
int awaitfs(struct await_target *fds, int nfds, int flags) {
50+
return errno_syscall(SYS_awaitfs, fds, nfds, flags);
51+
}
52+
53+
54+
void ck::eventloop::pump(void) {
55+
ck::vec<struct await_target> targs;
56+
57+
auto add_fd = [&](int fd, int mask, ck::object *obj) {
58+
struct await_target targ = {0};
59+
targ.fd = fd;
60+
targ.awaiting = mask;
61+
targ.priv = (void *)obj;
62+
targs.push(move(targ));
63+
};
64+
65+
66+
for (auto &notifier : s_notifiers) {
67+
int fd = notifier->fd();
68+
int event = notifier->ev_mask();
69+
70+
add_fd(fd, event, notifier);
71+
}
72+
73+
74+
int index = awaitfs(targs.data(), targs.size(), 0);
75+
if (index >= 0) {
76+
auto occ = targs[index].occurred;
77+
if (occ & AWAITFS_READ) {
78+
auto event = new ck::event();
79+
event->type = CK_EVENT_READ;
80+
post_event(*(ck::object *)targs[index].priv, event);
81+
}
82+
83+
84+
if (occ & AWAITFS_WRITE) {
85+
auto event = new ck::event();
86+
event->type = CK_EVENT_WRITE;
87+
post_event(*(ck::object *)targs[index].priv, event);
88+
}
89+
}
90+
}
91+
92+
void ck::eventloop::post_event(ck::object &obj, ck::event *ev) {
93+
m_pending.empend(obj, ev);
94+
}
95+
96+
void ck::eventloop::dispatch(void) {
97+
// printf("dispatch: %d events\n", m_pending.size());
98+
// just loop through each event that needs to be dispatched and send them to
99+
// the clients
100+
for (auto &ev : m_pending) {
101+
ev.obj.event(*ev.ev);
102+
delete ev.ev;
103+
}
104+
m_pending.clear();
105+
}
106+
107+
108+
ck::eventloop *ck::eventloop::current(void) { return active_eventloop; }
109+
110+
111+
void ck::eventloop::register_notifier(ck::fsnotifier &n) {
112+
// printf("register notifier %p\n", &n);
113+
s_notifiers.set(&n);
114+
}
115+
116+
117+
void ck::eventloop::deregister_notifier(ck::fsnotifier &n) {
118+
// printf("dregister notifier %p\n", &n);
119+
s_notifiers.remove(&n);
120+
}
121+
122+
123+
124+
/////////////////////////////////////////////////////////////////////////////////////
125+
126+
127+
128+
ck::fsnotifier::fsnotifier(int fd, int event_mask)
129+
: m_fd(fd), m_ev_mask(event_mask) {
130+
set_active(true);
131+
}
132+
133+
134+
ck::fsnotifier::~fsnotifier(void) { set_active(false); }
135+
136+
void ck::fsnotifier::set_active(bool a) {
137+
if (a) {
138+
ck::eventloop::register_notifier(*this);
139+
} else {
140+
ck::eventloop::deregister_notifier(*this);
141+
}
142+
}
143+
144+
145+
bool ck::fsnotifier::event(const ck::event & ev) {
146+
147+
if (ev.type == CK_EVENT_READ && on_read) {
148+
on_read();
149+
}
150+
151+
if (ev.type == CK_EVENT_WRITE && on_write) {
152+
on_write();
153+
}
154+
return true;
155+
}

0 commit comments

Comments
 (0)