-
-
Notifications
You must be signed in to change notification settings - Fork 411
/
event.c
137 lines (110 loc) · 3.07 KB
/
event.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include "event.h"
#include "asio.h"
#include "../actor/actor.h"
#include "../mem/pool.h"
#include "../sched/scheduler.h"
#include "ponyassert.h"
#include <string.h>
PONY_API asio_event_t* pony_asio_event_create(pony_actor_t* owner, int fd,
uint32_t flags, uint64_t nsec, bool noisy)
{
if((flags == ASIO_DISPOSABLE) || (flags == ASIO_DESTROYED))
return NULL;
pony_type_t* type = *(pony_type_t**)owner;
uint32_t msg_id = type->event_notify;
if(msg_id == (uint32_t)-1)
return NULL;
asio_event_t* ev = POOL_ALLOC(asio_event_t);
ev->magic = ev;
ev->owner = owner;
ev->msg_id = msg_id;
ev->fd = fd;
ev->flags = flags;
ev->noisy = noisy;
ev->nsec = nsec;
ev->writeable = false;
ev->readable = false;
// The event is effectively being sent to another thread, so mark it here.
pony_ctx_t* ctx = pony_ctx();
pony_gc_send(ctx);
pony_traceknown(ctx, owner, type, PONY_TRACE_OPAQUE);
pony_send_done(ctx);
pony_asio_event_subscribe(ev);
return ev;
}
PONY_API void pony_asio_event_destroy(asio_event_t* ev)
{
if((ev == NULL) || (ev->magic != ev) || (ev->flags != ASIO_DISPOSABLE))
{
pony_assert(0);
return;
}
ev->flags = ASIO_DESTROYED;
// When we let go of an event, we treat it as if we had received it back from
// the asio thread.
pony_ctx_t* ctx = pony_ctx();
pony_gc_recv(ctx);
pony_traceunknown(ctx, ev->owner, PONY_TRACE_OPAQUE);
pony_recv_done(ctx);
POOL_FREE(asio_event_t, ev);
}
PONY_API int pony_asio_event_fd(asio_event_t* ev)
{
if(ev == NULL)
return -1;
return ev->fd;
}
PONY_API bool pony_asio_event_get_disposable(asio_event_t* ev)
{
if(ev == NULL)
return false;
return (ev->flags == ASIO_DISPOSABLE);
}
PONY_API bool pony_asio_event_get_writeable(asio_event_t* ev)
{
if(ev == NULL)
return false;
return ev->writeable;
}
PONY_API void pony_asio_event_set_writeable(asio_event_t* ev, bool writeable)
{
if(ev != NULL)
ev->writeable = writeable;
}
PONY_API bool pony_asio_event_get_readable(asio_event_t* ev)
{
if(ev == NULL)
return false;
return ev->readable;
}
PONY_API void pony_asio_event_set_readable(asio_event_t* ev, bool readable)
{
if(ev != NULL)
ev->readable = readable;
}
PONY_API uint64_t pony_asio_event_nsec(asio_event_t* ev)
{
if(ev == NULL)
return 0;
return ev->nsec;
}
PONY_API void pony_asio_event_send(asio_event_t* ev, uint32_t flags,
uint32_t arg)
{
#ifdef PLATFORM_IS_WINDOWS
// On Windows, this can be called from an IOCP callback thread, which may
// not have a pony_ctx() associated with it yet.
pony_register_thread();
#endif
asio_msg_t* m = (asio_msg_t*)pony_alloc_msg(POOL_INDEX(sizeof(asio_msg_t)),
ev->msg_id);
m->event = ev;
m->flags = flags;
m->arg = arg;
// ASIO messages technically are application messages, but since they have no
// sender they aren't covered by backpressure. We pass false for an early
// bailout in the backpressure code.
pony_sendv(pony_ctx(), ev->owner, &m->msg, &m->msg, false);
// maybe wake up a scheduler thread if they've all fallen asleep
ponyint_sched_maybe_wakeup_if_all_asleep(-1);
}