mirror of
https://github.com/ashinn/chibi-scheme.git
synced 2025-05-19 05:39:18 +02:00
Binding a socket makes it non-blocking by default.
Allowing primitives (currently only send/receive) to block just once with SEXP_G_IO_BLOCK_ONCE_ERROR.
This commit is contained in:
parent
4c5788ff11
commit
f759076d2b
5 changed files with 21 additions and 5 deletions
2
eval.c
2
eval.c
|
@ -490,6 +490,8 @@ void sexp_init_eval_context_globals (sexp ctx) {
|
||||||
#if SEXP_USE_GREEN_THREADS
|
#if SEXP_USE_GREEN_THREADS
|
||||||
sexp_global(ctx, SEXP_G_IO_BLOCK_ERROR)
|
sexp_global(ctx, SEXP_G_IO_BLOCK_ERROR)
|
||||||
= sexp_user_exception(ctx, SEXP_FALSE, "I/O would block", SEXP_NULL);
|
= sexp_user_exception(ctx, SEXP_FALSE, "I/O would block", SEXP_NULL);
|
||||||
|
sexp_global(ctx, SEXP_G_IO_BLOCK_ONCE_ERROR)
|
||||||
|
= sexp_user_exception(ctx, SEXP_FALSE, "I/O would block once", SEXP_NULL);
|
||||||
sexp_global(ctx, SEXP_G_THREADS_FRONT) = SEXP_NULL;
|
sexp_global(ctx, SEXP_G_THREADS_FRONT) = SEXP_NULL;
|
||||||
sexp_global(ctx, SEXP_G_THREADS_BACK) = SEXP_NULL;
|
sexp_global(ctx, SEXP_G_THREADS_BACK) = SEXP_NULL;
|
||||||
sexp_global(ctx, SEXP_G_THREADS_SIGNALS) = SEXP_ZERO;
|
sexp_global(ctx, SEXP_G_THREADS_SIGNALS) = SEXP_ZERO;
|
||||||
|
|
|
@ -1232,6 +1232,7 @@ enum sexp_context_globals {
|
||||||
#endif
|
#endif
|
||||||
#if SEXP_USE_GREEN_THREADS
|
#if SEXP_USE_GREEN_THREADS
|
||||||
SEXP_G_IO_BLOCK_ERROR,
|
SEXP_G_IO_BLOCK_ERROR,
|
||||||
|
SEXP_G_IO_BLOCK_ONCE_ERROR,
|
||||||
SEXP_G_THREADS_SCHEDULER,
|
SEXP_G_THREADS_SCHEDULER,
|
||||||
SEXP_G_THREADS_FRONT,
|
SEXP_G_THREADS_FRONT,
|
||||||
SEXP_G_THREADS_BACK,
|
SEXP_G_THREADS_BACK,
|
||||||
|
|
|
@ -39,7 +39,7 @@ sexp sexp_sendto (sexp ctx, sexp self, int sock, const void* buffer, size_t len,
|
||||||
f = sexp_global(ctx, SEXP_G_THREADS_BLOCKER);
|
f = sexp_global(ctx, SEXP_G_THREADS_BLOCKER);
|
||||||
if (sexp_applicablep(f)) {
|
if (sexp_applicablep(f)) {
|
||||||
sexp_apply2(ctx, f, sexp_make_fixnum(sock), timeout);
|
sexp_apply2(ctx, f, sexp_make_fixnum(sock), timeout);
|
||||||
return sexp_global(ctx, SEXP_G_IO_BLOCK_ERROR);
|
return sexp_global(ctx, SEXP_G_IO_BLOCK_ONCE_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -57,15 +57,24 @@ sexp sexp_recvfrom (sexp ctx, sexp self, int sock, void* buffer, size_t len, int
|
||||||
f = sexp_global(ctx, SEXP_G_THREADS_BLOCKER);
|
f = sexp_global(ctx, SEXP_G_THREADS_BLOCKER);
|
||||||
if (sexp_applicablep(f)) {
|
if (sexp_applicablep(f)) {
|
||||||
sexp_apply2(ctx, f, sexp_make_fixnum(sock), timeout);
|
sexp_apply2(ctx, f, sexp_make_fixnum(sock), timeout);
|
||||||
return sexp_global(ctx, SEXP_G_IO_BLOCK_ERROR);
|
return sexp_global(ctx, SEXP_G_IO_BLOCK_ONCE_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return sexp_make_fixnum(res);
|
return sexp_make_fixnum(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we're listening on a socket from Scheme, we most likely want it */
|
/* If we're binding or listening on a socket from Scheme, we most */
|
||||||
/* to be non-blocking. */
|
/* likely want it to be non-blocking. */
|
||||||
|
|
||||||
|
sexp sexp_bind (sexp ctx, sexp self, int fd, struct sockaddr* addr, socklen_t addr_len) {
|
||||||
|
int res = bind(fd, addr, addr_len);
|
||||||
|
#if SEXP_USE_GREEN_THREADS
|
||||||
|
if (res >= 0)
|
||||||
|
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
|
||||||
|
#endif
|
||||||
|
return (res == 0) ? SEXP_TRUE : SEXP_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
sexp sexp_listen (sexp ctx, sexp self, sexp fileno, sexp backlog) {
|
sexp sexp_listen (sexp ctx, sexp self, sexp fileno, sexp backlog) {
|
||||||
int fd, res;
|
int fd, res;
|
||||||
|
|
|
@ -32,7 +32,8 @@
|
||||||
|
|
||||||
;;> Bind a name to a socket.
|
;;> Bind a name to a socket.
|
||||||
|
|
||||||
(define-c errno bind (fileno sockaddr int))
|
(define-c sexp (bind "sexp_bind")
|
||||||
|
((value ctx sexp) (value self sexp) fileno sockaddr int))
|
||||||
|
|
||||||
;;> Listen on a socket.
|
;;> Listen on a socket.
|
||||||
|
|
||||||
|
|
3
vm.c
3
vm.c
|
@ -883,6 +883,9 @@ static int sexp_check_type(sexp ctx, sexp a, sexp b) {
|
||||||
if (sexp_exceptionp(x)) { \
|
if (sexp_exceptionp(x)) { \
|
||||||
if (x == sexp_global(ctx, SEXP_G_IO_BLOCK_ERROR)) { \
|
if (x == sexp_global(ctx, SEXP_G_IO_BLOCK_ERROR)) { \
|
||||||
fuel = 0; ip--; goto loop; \
|
fuel = 0; ip--; goto loop; \
|
||||||
|
} else if (x == sexp_global(ctx, SEXP_G_IO_BLOCK_ONCE_ERROR)) { \
|
||||||
|
stack[top-i+1] = SEXP_ZERO; \
|
||||||
|
fuel = 0; ip--; goto loop; \
|
||||||
} else { \
|
} else { \
|
||||||
top -= i; \
|
top -= i; \
|
||||||
_ARG1 = x; \
|
_ARG1 = x; \
|
||||||
|
|
Loading…
Add table
Reference in a new issue