Skip to content

Commit 8298243

Browse files
committed
Merge branch 'windows-threaded-event-loop'
2 parents 79ac58b + 210eb2b commit 8298243

File tree

7 files changed

+84
-104
lines changed

7 files changed

+84
-104
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ if(APPLE)
55
set(CMAKE_OSX_ARCHITECTURES "x86_64;arm64")
66
endif()
77

8-
project(serialosc VERSION 1.4.5)
8+
project(serialosc VERSION 1.4.6)
99

1010
set(CMAKE_C_STANDARD 17)
1111

src/serialosc-device/event_loop/windows.c

Lines changed: 78 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -24,21 +24,14 @@
2424
#include <serialosc/serialosc.h>
2525
#include <serialosc/ipc.h>
2626

27-
#ifdef _LP64
28-
#define PRIdword "d"
29-
#define PRIudword "u"
30-
#else
31-
#define PRIdword "ld"
32-
#define PRIudword "lu"
33-
#endif
34-
3527
static int
36-
recv_msg(struct sosc_state *state, int ipc_fd)
28+
recv_ipc_msg(struct sosc_state *state, int ipc_fd)
3729
{
3830
struct sosc_ipc_msg msg;
3931

40-
if (sosc_ipc_msg_read(ipc_fd, &msg) <= 0)
32+
if (sosc_ipc_msg_read(ipc_fd, &msg) <= 0) {
4133
return 0;
34+
}
4235

4336
switch (msg.type) {
4437
case SOSC_PROCESS_SHOULD_EXIT:
@@ -50,124 +43,111 @@ recv_msg(struct sosc_state *state, int ipc_fd)
5043
}
5144
}
5245

53-
struct poll_thread_ctx {
54-
struct sosc_state *state;
55-
HANDLE wakeup_handle;
56-
};
46+
int
47+
wait_for_serial_input(HANDLE hres, LPOVERLAPPED ov, DWORD timeout)
48+
{
49+
DWORD event_mask;
50+
int result = 0;
51+
52+
SetCommMask(hres, EV_RXCHAR);
53+
54+
if (!WaitCommEvent(hres, &event_mask, ov)) {
55+
if (GetLastError() == ERROR_IO_PENDING) {
56+
switch (WaitForSingleObject(ov->hEvent, timeout)) {
57+
case WAIT_OBJECT_0:
58+
result = 0;
59+
break;
60+
case WAIT_TIMEOUT:
61+
result = 1;
62+
break;
63+
default:
64+
result = -1;
65+
break;
66+
}
67+
} else {
68+
result = -1;
69+
}
70+
} else {
71+
result = 0;
72+
}
73+
74+
return result;
75+
}
5776

5877
static DWORD WINAPI
59-
stdin_poll_thread(LPVOID _ctx)
78+
stdin_poll_thread(LPVOID arg)
6079
{
61-
struct poll_thread_ctx *ctx = _ctx;
80+
struct sosc_state *state = arg;
6281

6382
SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), ENABLE_PROCESSED_INPUT);
6483

65-
for (;;) {
66-
recv_msg(ctx->state, STDIN_FILENO);
67-
SetEvent(ctx->wakeup_handle);
84+
while (state->running) {
85+
recv_ipc_msg(state, STDIN_FILENO);
6886
}
6987

7088
return 0;
7189
}
7290

73-
static bool
74-
wait_for_serial_input(HANDLE file, LPOVERLAPPED ov)
91+
static DWORD WINAPI
92+
serial_poll_thread(LPVOID arg)
7593
{
76-
DWORD evt_mask;
77-
78-
SetCommMask(file, EV_RXCHAR);
79-
80-
if (!WaitCommEvent(file, &evt_mask, ov)) {
81-
switch (GetLastError()) {
82-
case ERROR_IO_PENDING:
83-
break;
84-
/* evidently we get this when the monome is unplugged? */
85-
case ERROR_ACCESS_DENIED:
86-
return false;
87-
default:
88-
fprintf(stderr, "wait_for_serial_input() error: %"PRIdword"\n", GetLastError());
89-
return false;
90-
}
91-
}
92-
93-
return true;
94-
}
94+
struct sosc_state *state = arg;
9595

96-
int
97-
sosc_event_loop(struct sosc_state *state)
98-
{
9996
OVERLAPPED ov = {0, 0, {{0, 0}}};
100-
HANDLE hres, wait_handles[3];
101-
WSANETWORKEVENTS network_events;
102-
struct poll_thread_ctx ctx;
103-
ssize_t nbytes;
97+
ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
10498
int status;
10599

106-
wait_handles[0] = ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
107-
108-
wait_handles[1] = WSACreateEvent();
109-
WSAEventSelect(lo_server_get_socket_fd(state->server),
110-
wait_handles[1], FD_READ);
111-
112-
wait_handles[2] = CreateEvent(NULL, TRUE, FALSE, NULL);
113-
114-
state->running = 1;
115-
116-
if (state->ipc_in_fd > -1 || 1) {
117-
ctx.state = state;
118-
ctx.wakeup_handle = wait_handles[2];
119-
120-
CreateThread(NULL, 0, stdin_poll_thread, &ctx, 0, NULL);
121-
}
122-
123-
hres = (HANDLE) _get_osfhandle(monome_get_fd(state->monome));
124-
125-
if (!wait_for_serial_input(hres, &ov)) {
126-
return 1;
127-
}
100+
HANDLE monome_handle = (HANDLE) _get_osfhandle(monome_get_fd(state->monome));
128101

129102
while (state->running) {
130-
switch (WaitForMultipleObjects(3, wait_handles, FALSE, INFINITE)) {
131-
case WAIT_OBJECT_0:
103+
if (wait_for_serial_input(monome_handle, &ov, INFINITE) == 0) {
132104
do {
133105
status = monome_event_handle_next(state->monome);
134-
135-
if (status < 0) {
136-
return 1;
137-
}
138106
} while (status > 0);
139107

140-
// reset the event and wait for more input
141-
if (!wait_for_serial_input(hres, &ov)) {
142-
return 1;
108+
if (status < 0) {
109+
goto err;
143110
}
111+
} else {
112+
goto err;
113+
}
114+
}
144115

145-
break;
116+
err:
117+
CloseHandle(ov.hEvent);
118+
return 0;
119+
}
146120

147-
case WAIT_OBJECT_0 + 1:
148-
WSAEnumNetworkEvents(lo_server_get_socket_fd(state->server),
149-
wait_handles[1],
150-
&network_events);
151-
do {
152-
nbytes = lo_server_recv_noblock(state->server, 0);
153-
} while (nbytes > 0);
121+
static DWORD WINAPI
122+
osc_poll_thread(LPVOID arg)
123+
{
124+
struct sosc_state *state = arg;
154125

155-
break;
126+
while (state->running) {
127+
lo_server_recv(state->server);
128+
}
156129

157-
case WAIT_OBJECT_0 + 2:
158-
ResetEvent(wait_handles[2]);
159-
break;
130+
return 0;
131+
}
160132

161-
case WAIT_TIMEOUT:
162-
break;
133+
int
134+
sosc_event_loop(struct sosc_state *state)
135+
{
136+
HANDLE threads[3];
163137

164-
case WAIT_ABANDONED_0:
165-
case WAIT_FAILED:
166-
fprintf(stderr, "event_loop(): wait failed: %"PRIdword"\n",
167-
GetLastError());
168-
return 1;
169-
}
138+
state->running = true;
139+
140+
threads[0] = CreateThread(NULL, 0, serial_poll_thread, state, 0, NULL);
141+
threads[1] = CreateThread(NULL, 0, osc_poll_thread, state, 0, NULL);
142+
143+
if (state->ipc_in_fd > -1) {
144+
threads[2] = CreateThread(NULL, 0, stdin_poll_thread, state, 0, NULL);
145+
} else {
146+
// wait for a dummy event if no ipc
147+
threads[2] = CreateEvent(NULL, TRUE, FALSE, NULL);
170148
}
171149

150+
WaitForMultipleObjects(3, threads, FALSE, INFINITE);
151+
172152
return 0;
173153
}

third-party/libmonome

third-party/libuv

Submodule libuv updated 139 files

wscript

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ out = "build"
1010
# change this stuff
1111

1212
APPNAME = "serialosc"
13-
VERSION = "1.4.5"
13+
VERSION = "1.4.6"
1414

1515
#
1616
# dep checking functions

0 commit comments

Comments
 (0)