mirror of
https://github.com/janet-lang/janet
synced 2024-12-26 00:10:27 +00:00
Merge branch 'janet-lang:master' into master
This commit is contained in:
commit
b4b1c7d80b
@ -1,6 +1,10 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
## ??? - Unreleased
|
||||||
|
- Make imperative arithmetic macros variadic
|
||||||
|
- `ev/connect` now yields to the event loop instead of blocking while waiting for an ACK.
|
||||||
|
|
||||||
## 1.28.0 - 2023-05-13
|
## 1.28.0 - 2023-05-13
|
||||||
- Various bug fixes
|
- Various bug fixes
|
||||||
- Make nested short-fn's behave a bit more predictably (it is still not recommended to nest short-fns).
|
- Make nested short-fn's behave a bit more predictably (it is still not recommended to nest short-fns).
|
||||||
|
@ -147,10 +147,10 @@
|
|||||||
(defn dec "Returns x - 1." [x] (- x 1))
|
(defn dec "Returns x - 1." [x] (- x 1))
|
||||||
(defmacro ++ "Increments the var x by 1." [x] ~(set ,x (,+ ,x ,1)))
|
(defmacro ++ "Increments the var x by 1." [x] ~(set ,x (,+ ,x ,1)))
|
||||||
(defmacro -- "Decrements the var x by 1." [x] ~(set ,x (,- ,x ,1)))
|
(defmacro -- "Decrements the var x by 1." [x] ~(set ,x (,- ,x ,1)))
|
||||||
(defmacro += "Increments the var x by n." [x n] ~(set ,x (,+ ,x ,n)))
|
(defmacro += "Increments the var x by n." [x & ns] ~(set ,x (,+ ,x ,;ns)))
|
||||||
(defmacro -= "Decrements the var x by n." [x n] ~(set ,x (,- ,x ,n)))
|
(defmacro -= "Decrements the var x by n." [x & ns] ~(set ,x (,- ,x ,;ns)))
|
||||||
(defmacro *= "Shorthand for (set x (\\* x n))." [x n] ~(set ,x (,* ,x ,n)))
|
(defmacro *= "Shorthand for (set x (\\* x n))." [x & ns] ~(set ,x (,* ,x ,;ns)))
|
||||||
(defmacro /= "Shorthand for (set x (/ x n))." [x n] ~(set ,x (,/ ,x ,n)))
|
(defmacro /= "Shorthand for (set x (/ x n))." [x & ns] ~(set ,x (,/ ,x ,;ns)))
|
||||||
(defmacro %= "Shorthand for (set x (% x n))." [x n] ~(set ,x (,% ,x ,n)))
|
(defmacro %= "Shorthand for (set x (% x n))." [x n] ~(set ,x (,% ,x ,n)))
|
||||||
|
|
||||||
(defmacro assert
|
(defmacro assert
|
||||||
@ -2142,6 +2142,19 @@
|
|||||||
:buffer (string x)
|
:buffer (string x)
|
||||||
x))
|
x))
|
||||||
|
|
||||||
|
(defn thaw
|
||||||
|
`Thaw an object (make it mutable) and do a deep copy, making
|
||||||
|
child value also mutable. Closures, fibers, and abstract
|
||||||
|
types will not be recursively thawed, but all other types will`
|
||||||
|
[ds]
|
||||||
|
(case (type ds)
|
||||||
|
:array (walk-ind thaw ds)
|
||||||
|
:tuple (walk-ind thaw ds)
|
||||||
|
:table (walk-dict thaw (table/proto-flatten ds))
|
||||||
|
:struct (walk-dict thaw (struct/proto-flatten ds))
|
||||||
|
:string (buffer ds)
|
||||||
|
ds))
|
||||||
|
|
||||||
(defn macex
|
(defn macex
|
||||||
``Expand macros completely.
|
``Expand macros completely.
|
||||||
`on-binding` is an optional callback for whenever a normal symbolic binding
|
`on-binding` is an optional callback for whenever a normal symbolic binding
|
||||||
|
@ -1502,6 +1502,10 @@ void janet_loop1_impl(int has_timeout, JanetTimestamp to) {
|
|||||||
state = state->_next;
|
state = state->_next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* Close the stream if requested and no more listeners are left */
|
||||||
|
if ((stream->flags & JANET_STREAM_TOCLOSE) && !stream->state) {
|
||||||
|
janet_stream_close(stream);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1656,6 +1660,10 @@ void janet_loop1_impl(int has_timeout, JanetTimestamp timeout) {
|
|||||||
janet_unlisten(state, 0);
|
janet_unlisten(state, 0);
|
||||||
state = next_state;
|
state = next_state;
|
||||||
}
|
}
|
||||||
|
/* Close the stream if requested and no more listeners are left */
|
||||||
|
if ((stream->flags & JANET_STREAM_TOCLOSE) && !stream->state) {
|
||||||
|
janet_stream_close(stream);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1854,6 +1862,10 @@ void janet_loop1_impl(int has_timeout, JanetTimestamp timeout) {
|
|||||||
|
|
||||||
state = next_state;
|
state = next_state;
|
||||||
}
|
}
|
||||||
|
/* Close the stream if requested and no more listeners are left */
|
||||||
|
if ((stream->flags & JANET_STREAM_TOCLOSE) && !stream->state) {
|
||||||
|
janet_stream_close(stream);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1957,6 +1969,7 @@ void janet_loop1_impl(int has_timeout, JanetTimestamp timeout) {
|
|||||||
JanetAsyncStatus status3 = JANET_ASYNC_STATUS_NOT_DONE;
|
JanetAsyncStatus status3 = JANET_ASYNC_STATUS_NOT_DONE;
|
||||||
JanetAsyncStatus status4 = JANET_ASYNC_STATUS_NOT_DONE;
|
JanetAsyncStatus status4 = JANET_ASYNC_STATUS_NOT_DONE;
|
||||||
state->event = pfd;
|
state->event = pfd;
|
||||||
|
JanetStream *stream = state->stream;
|
||||||
if (mask & POLLOUT)
|
if (mask & POLLOUT)
|
||||||
status1 = state->machine(state, JANET_ASYNC_EVENT_WRITE);
|
status1 = state->machine(state, JANET_ASYNC_EVENT_WRITE);
|
||||||
if (mask & POLLIN)
|
if (mask & POLLIN)
|
||||||
@ -1970,6 +1983,10 @@ void janet_loop1_impl(int has_timeout, JanetTimestamp timeout) {
|
|||||||
status3 == JANET_ASYNC_STATUS_DONE ||
|
status3 == JANET_ASYNC_STATUS_DONE ||
|
||||||
status4 == JANET_ASYNC_STATUS_DONE)
|
status4 == JANET_ASYNC_STATUS_DONE)
|
||||||
janet_unlisten(state, 0);
|
janet_unlisten(state, 0);
|
||||||
|
/* Close the stream if requested and no more listeners are left */
|
||||||
|
if ((stream->flags & JANET_STREAM_TOCLOSE) && !stream->state) {
|
||||||
|
janet_stream_close(stream);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2456,7 +2473,8 @@ void janet_ev_recvfrom(JanetStream *stream, JanetBuffer *buf, int32_t nbytes, in
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
JANET_ASYNC_WRITEMODE_WRITE,
|
JANET_ASYNC_WRITEMODE_WRITE,
|
||||||
JANET_ASYNC_WRITEMODE_SEND,
|
JANET_ASYNC_WRITEMODE_SEND,
|
||||||
JANET_ASYNC_WRITEMODE_SENDTO
|
JANET_ASYNC_WRITEMODE_SENDTO,
|
||||||
|
JANET_ASYNC_WRITEMODE_CONNECT
|
||||||
} JanetWriteMode;
|
} JanetWriteMode;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -2480,6 +2498,31 @@ typedef struct {
|
|||||||
#endif
|
#endif
|
||||||
} StateWrite;
|
} StateWrite;
|
||||||
|
|
||||||
|
static JanetAsyncStatus handle_connect(JanetListenerState *s) {
|
||||||
|
#ifdef JANET_WINDOWS
|
||||||
|
int res = 0;
|
||||||
|
int size = sizeof(res);
|
||||||
|
int r = getsockopt((SOCKET)s->stream->handle, SOL_SOCKET, SO_ERROR, (char *)&res, &size);
|
||||||
|
#else
|
||||||
|
int res = 0;
|
||||||
|
socklen_t size = sizeof res;
|
||||||
|
int r = getsockopt(s->stream->handle, SOL_SOCKET, SO_ERROR, &res, &size);
|
||||||
|
#endif
|
||||||
|
if (r == 0) {
|
||||||
|
if (res == 0) {
|
||||||
|
janet_schedule(s->fiber, janet_wrap_abstract(s->stream));
|
||||||
|
} else {
|
||||||
|
s->stream->flags |= JANET_STREAM_TOCLOSE;
|
||||||
|
janet_cancel(s->fiber, janet_cstringv(strerror(res)));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
s->stream->flags |= JANET_STREAM_TOCLOSE;
|
||||||
|
janet_cancel(s->fiber, janet_ev_lasterr());
|
||||||
|
}
|
||||||
|
return JANET_ASYNC_STATUS_DONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
JanetAsyncStatus ev_machine_write(JanetListenerState *s, JanetAsyncEvent event) {
|
JanetAsyncStatus ev_machine_write(JanetListenerState *s, JanetAsyncEvent event) {
|
||||||
StateWrite *state = (StateWrite *) s;
|
StateWrite *state = (StateWrite *) s;
|
||||||
switch (event) {
|
switch (event) {
|
||||||
@ -2509,6 +2552,11 @@ JanetAsyncStatus ev_machine_write(JanetListenerState *s, JanetAsyncEvent event)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case JANET_ASYNC_EVENT_USER: {
|
case JANET_ASYNC_EVENT_USER: {
|
||||||
|
#ifdef JANET_NET
|
||||||
|
if (state->mode == JANET_ASYNC_WRITEMODE_CONNECT) {
|
||||||
|
return handle_connect(s);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
/* Begin write */
|
/* Begin write */
|
||||||
int32_t len;
|
int32_t len;
|
||||||
const uint8_t *bytes;
|
const uint8_t *bytes;
|
||||||
@ -2572,6 +2620,11 @@ JanetAsyncStatus ev_machine_write(JanetListenerState *s, JanetAsyncEvent event)
|
|||||||
janet_cancel(s->fiber, janet_cstringv("stream hup"));
|
janet_cancel(s->fiber, janet_cstringv("stream hup"));
|
||||||
return JANET_ASYNC_STATUS_DONE;
|
return JANET_ASYNC_STATUS_DONE;
|
||||||
case JANET_ASYNC_EVENT_WRITE: {
|
case JANET_ASYNC_EVENT_WRITE: {
|
||||||
|
#ifdef JANET_NET
|
||||||
|
if (state->mode == JANET_ASYNC_WRITEMODE_CONNECT) {
|
||||||
|
return handle_connect(s);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
int32_t start, len;
|
int32_t start, len;
|
||||||
const uint8_t *bytes;
|
const uint8_t *bytes;
|
||||||
start = state->start;
|
start = state->start;
|
||||||
@ -2674,6 +2727,10 @@ void janet_ev_sendto_buffer(JanetStream *stream, JanetBuffer *buf, void *dest, i
|
|||||||
void janet_ev_sendto_string(JanetStream *stream, JanetString str, void *dest, int flags) {
|
void janet_ev_sendto_string(JanetStream *stream, JanetString str, void *dest, int flags) {
|
||||||
janet_ev_write_generic(stream, (void *) str, dest, JANET_ASYNC_WRITEMODE_SENDTO, 0, flags);
|
janet_ev_write_generic(stream, (void *) str, dest, JANET_ASYNC_WRITEMODE_SENDTO, 0, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void janet_ev_connect(JanetStream *stream, int flags) {
|
||||||
|
janet_ev_write_generic(stream, NULL, NULL, JANET_ASYNC_WRITEMODE_CONNECT, 0, flags);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* For a pipe ID */
|
/* For a pipe ID */
|
||||||
|
@ -477,14 +477,20 @@ JANET_CORE_FN(cfun_net_connect,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Wrap socket in abstract type JanetStream */
|
||||||
|
JanetStream *stream = make_stream(sock, JANET_STREAM_READABLE | JANET_STREAM_WRITABLE);
|
||||||
|
|
||||||
|
/* Set up the socket for non-blocking IO before connecting */
|
||||||
|
janet_net_socknoblock(sock);
|
||||||
|
|
||||||
/* Connect to socket */
|
/* Connect to socket */
|
||||||
#ifdef JANET_WINDOWS
|
#ifdef JANET_WINDOWS
|
||||||
int status = WSAConnect(sock, addr, addrlen, NULL, NULL, NULL, NULL);
|
int status = WSAConnect(sock, addr, addrlen, NULL, NULL, NULL, NULL);
|
||||||
Janet lasterr = janet_ev_lasterr();
|
int err = WSAGetLastError();
|
||||||
freeaddrinfo(ai);
|
freeaddrinfo(ai);
|
||||||
#else
|
#else
|
||||||
int status = connect(sock, addr, addrlen);
|
int status = connect(sock, addr, addrlen);
|
||||||
Janet lasterr = janet_ev_lasterr();
|
int err = errno;
|
||||||
if (is_unix) {
|
if (is_unix) {
|
||||||
janet_free(ai);
|
janet_free(ai);
|
||||||
} else {
|
} else {
|
||||||
@ -492,17 +498,22 @@ JANET_CORE_FN(cfun_net_connect,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (status == -1) {
|
if (status != 0) {
|
||||||
JSOCKCLOSE(sock);
|
#ifdef JANET_WINDOWS
|
||||||
janet_panicf("could not connect socket: %V", lasterr);
|
if (err != WSAEWOULDBLOCK) {
|
||||||
|
#else
|
||||||
|
if (err != EINPROGRESS) {
|
||||||
|
#endif
|
||||||
|
JSOCKCLOSE(sock);
|
||||||
|
Janet lasterr = janet_ev_lasterr();
|
||||||
|
janet_panicf("could not connect socket: %V", lasterr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set up the socket for non-blocking IO after connect - TODO - non-blocking connect? */
|
/* Handle the connect() result in the event loop*/
|
||||||
janet_net_socknoblock(sock);
|
janet_ev_connect(stream, MSG_NOSIGNAL);
|
||||||
|
|
||||||
/* Wrap socket in abstract type JanetStream */
|
janet_await();
|
||||||
JanetStream *stream = make_stream(sock, JANET_STREAM_READABLE | JANET_STREAM_WRITABLE);
|
|
||||||
return janet_wrap_abstract(stream);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *serverify_socket(JSock sfd) {
|
static const char *serverify_socket(JSock sfd) {
|
||||||
|
@ -1380,14 +1380,32 @@ JANET_CORE_FN(os_time,
|
|||||||
}
|
}
|
||||||
|
|
||||||
JANET_CORE_FN(os_clock,
|
JANET_CORE_FN(os_clock,
|
||||||
"(os/clock)",
|
"(os/clock &opt source)",
|
||||||
"Return the number of whole + fractional seconds since some fixed point in time. The clock "
|
"Return the number of whole + fractional seconds of the requested clock source.\n\n"
|
||||||
"is guaranteed to be non-decreasing in real time.") {
|
"The `source` argument selects the clock source to use, when not specified the default "
|
||||||
|
"is `:realtime`:\n"
|
||||||
|
"- :realtime: Return the real (i.e., wall-clock) time. This clock is affected by discontinuous "
|
||||||
|
" jumps in the system time\n"
|
||||||
|
"- :monotonic: Return the number of whole + fractional seconds since some fixed point in "
|
||||||
|
" time. The clock is guaranteed to be non-decreasing in real time.\n"
|
||||||
|
"- :cputime: Return the CPU time consumed by this process (i.e. all threads in the process)\n") {
|
||||||
janet_sandbox_assert(JANET_SANDBOX_HRTIME);
|
janet_sandbox_assert(JANET_SANDBOX_HRTIME);
|
||||||
janet_fixarity(argc, 0);
|
janet_arity(argc, 0, 1);
|
||||||
(void) argv;
|
enum JanetTimeSource source = JANET_TIME_REALTIME;
|
||||||
|
if (argc == 1) {
|
||||||
|
JanetKeyword sourcestr = janet_getkeyword(argv, 0);
|
||||||
|
if (janet_cstrcmp(sourcestr, "realtime") == 0) {
|
||||||
|
source = JANET_TIME_REALTIME;
|
||||||
|
} else if (janet_cstrcmp(sourcestr, "monotonic") == 0) {
|
||||||
|
source = JANET_TIME_MONOTONIC;
|
||||||
|
} else if (janet_cstrcmp(sourcestr, "cputime") == 0) {
|
||||||
|
source = JANET_TIME_CPUTIME;
|
||||||
|
} else {
|
||||||
|
janet_panicf("expected :realtime, :monotonic, or :cputime, got %v", argv[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
struct timespec tv;
|
struct timespec tv;
|
||||||
if (janet_gettime(&tv)) janet_panic("could not get time");
|
if (janet_gettime(&tv, source)) janet_panic("could not get time");
|
||||||
double dtime = tv.tv_sec + (tv.tv_nsec / 1E9);
|
double dtime = tv.tv_sec + (tv.tv_nsec / 1E9);
|
||||||
return janet_wrap_number(dtime);
|
return janet_wrap_number(dtime);
|
||||||
}
|
}
|
||||||
|
@ -875,34 +875,73 @@ int32_t janet_sorted_keys(const JanetKV *dict, int32_t cap, int32_t *index_buffe
|
|||||||
/* Clock shims for various platforms */
|
/* Clock shims for various platforms */
|
||||||
#ifdef JANET_GETTIME
|
#ifdef JANET_GETTIME
|
||||||
#ifdef JANET_WINDOWS
|
#ifdef JANET_WINDOWS
|
||||||
int janet_gettime(struct timespec *spec) {
|
#include <profileapi.h>
|
||||||
FILETIME ftime;
|
int janet_gettime(struct timespec *spec, enum JanetTimeSource source) {
|
||||||
GetSystemTimeAsFileTime(&ftime);
|
if (source == JANET_TIME_REALTIME) {
|
||||||
int64_t wintime = (int64_t)(ftime.dwLowDateTime) | ((int64_t)(ftime.dwHighDateTime) << 32);
|
FILETIME ftime;
|
||||||
/* Windows epoch is January 1, 1601 apparently */
|
GetSystemTimeAsFileTime(&ftime);
|
||||||
wintime -= 116444736000000000LL;
|
int64_t wintime = (int64_t)(ftime.dwLowDateTime) | ((int64_t)(ftime.dwHighDateTime) << 32);
|
||||||
spec->tv_sec = wintime / 10000000LL;
|
/* Windows epoch is January 1, 1601 apparently */
|
||||||
/* Resolution is 100 nanoseconds. */
|
wintime -= 116444736000000000LL;
|
||||||
spec->tv_nsec = wintime % 10000000LL * 100;
|
spec->tv_sec = wintime / 10000000LL;
|
||||||
|
/* Resolution is 100 nanoseconds. */
|
||||||
|
spec->tv_nsec = wintime % 10000000LL * 100;
|
||||||
|
} else if (source == JANET_TIME_MONOTONIC) {
|
||||||
|
LARGE_INTEGER count;
|
||||||
|
LARGE_INTEGER perf_freq;
|
||||||
|
QueryPerformanceCounter(&count);
|
||||||
|
QueryPerformanceFrequency(&perf_freq);
|
||||||
|
spec->tv_sec = count.QuadPart / perf_freq.QuadPart;
|
||||||
|
spec->tv_nsec = (long)((count.QuadPart % perf_freq.QuadPart) * 1000000000 / perf_freq.QuadPart);
|
||||||
|
} else if (source == JANET_TIME_CPUTIME) {
|
||||||
|
FILETIME creationTime, exitTime, kernelTime, userTime;
|
||||||
|
GetProcessTimes(GetCurrentProcess(), &creationTime, &exitTime, &kernelTime, &userTime);
|
||||||
|
int64_t tmp = ((int64_t)userTime.dwHighDateTime << 32) + userTime.dwLowDateTime;
|
||||||
|
spec->tv_sec = tmp / 10000000LL;
|
||||||
|
spec->tv_nsec = tmp % 10000000LL * 100;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* clock_gettime() wasn't available on Mac until 10.12. */
|
/* clock_gettime() wasn't available on Mac until 10.12. */
|
||||||
#elif defined(JANET_APPLE) && !defined(MAC_OS_X_VERSION_10_12)
|
#elif defined(JANET_APPLE) && !defined(MAC_OS_X_VERSION_10_12)
|
||||||
#include <mach/clock.h>
|
#include <mach/clock.h>
|
||||||
#include <mach/mach.h>
|
#include <mach/mach.h>
|
||||||
int janet_gettime(struct timespec *spec) {
|
int janet_gettime(struct timespec *spec, enum JanetTimeSource source) {
|
||||||
clock_serv_t cclock;
|
if (source == JANET_TIME_REALTIME) {
|
||||||
mach_timespec_t mts;
|
clock_serv_t cclock;
|
||||||
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
|
mach_timespec_t mts;
|
||||||
clock_get_time(cclock, &mts);
|
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
|
||||||
mach_port_deallocate(mach_task_self(), cclock);
|
clock_get_time(cclock, &mts);
|
||||||
spec->tv_sec = mts.tv_sec;
|
mach_port_deallocate(mach_task_self(), cclock);
|
||||||
spec->tv_nsec = mts.tv_nsec;
|
spec->tv_sec = mts.tv_sec;
|
||||||
|
spec->tv_nsec = mts.tv_nsec;
|
||||||
|
} else if (source == JANET_TIME_MONOTONIC) {
|
||||||
|
clock_serv_t cclock;
|
||||||
|
int nsecs;
|
||||||
|
mach_msg_type_number_t count;
|
||||||
|
host_get_clock_service(mach_host_self(), clock, &cclock);
|
||||||
|
clock_get_attributes(cclock, CLOCK_GET_TIME_RES, (clock_attr_t)&nsecs, &count);
|
||||||
|
mach_port_deallocate(mach_task_self(), cclock);
|
||||||
|
clock_getres(CLOCK_MONOTONIC, spec);
|
||||||
|
}
|
||||||
|
if (source == JANET_TIME_CPUTIME) {
|
||||||
|
clock_t tmp = clock();
|
||||||
|
spec->tv_sec = tmp;
|
||||||
|
spec->tv_nsec = (tmp - spec->tv_sec) * 1.0e9;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
int janet_gettime(struct timespec *spec) {
|
int janet_gettime(struct timespec *spec, enum JanetTimeSource source) {
|
||||||
return clock_gettime(CLOCK_REALTIME, spec);
|
clockid_t cid = JANET_TIME_REALTIME;
|
||||||
|
if (source == JANET_TIME_REALTIME) {
|
||||||
|
cid = CLOCK_REALTIME;
|
||||||
|
} else if (source == JANET_TIME_MONOTONIC) {
|
||||||
|
cid = CLOCK_MONOTONIC;
|
||||||
|
} else if (source == JANET_TIME_CPUTIME) {
|
||||||
|
cid = CLOCK_PROCESS_CPUTIME_ID;
|
||||||
|
}
|
||||||
|
return clock_gettime(cid, spec);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
@ -126,7 +126,12 @@ void janet_core_cfuns_ext(JanetTable *env, const char *regprefix, const JanetReg
|
|||||||
|
|
||||||
/* Clock gettime */
|
/* Clock gettime */
|
||||||
#ifdef JANET_GETTIME
|
#ifdef JANET_GETTIME
|
||||||
int janet_gettime(struct timespec *spec);
|
enum JanetTimeSource {
|
||||||
|
JANET_TIME_REALTIME,
|
||||||
|
JANET_TIME_MONOTONIC,
|
||||||
|
JANET_TIME_CPUTIME
|
||||||
|
};
|
||||||
|
int janet_gettime(struct timespec *spec, enum JanetTimeSource source);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* strdup */
|
/* strdup */
|
||||||
|
@ -568,6 +568,7 @@ typedef void *JanetAbstract;
|
|||||||
#define JANET_STREAM_WRITABLE 0x400
|
#define JANET_STREAM_WRITABLE 0x400
|
||||||
#define JANET_STREAM_ACCEPTABLE 0x800
|
#define JANET_STREAM_ACCEPTABLE 0x800
|
||||||
#define JANET_STREAM_UDPSERVER 0x1000
|
#define JANET_STREAM_UDPSERVER 0x1000
|
||||||
|
#define JANET_STREAM_TOCLOSE 0x10000
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
JANET_ASYNC_EVENT_INIT,
|
JANET_ASYNC_EVENT_INIT,
|
||||||
@ -1479,6 +1480,7 @@ JANET_API void janet_ev_readchunk(JanetStream *stream, JanetBuffer *buf, int32_t
|
|||||||
JANET_API void janet_ev_recv(JanetStream *stream, JanetBuffer *buf, int32_t nbytes, int flags);
|
JANET_API void janet_ev_recv(JanetStream *stream, JanetBuffer *buf, int32_t nbytes, int flags);
|
||||||
JANET_API void janet_ev_recvchunk(JanetStream *stream, JanetBuffer *buf, int32_t nbytes, int flags);
|
JANET_API void janet_ev_recvchunk(JanetStream *stream, JanetBuffer *buf, int32_t nbytes, int flags);
|
||||||
JANET_API void janet_ev_recvfrom(JanetStream *stream, JanetBuffer *buf, int32_t nbytes, int flags);
|
JANET_API void janet_ev_recvfrom(JanetStream *stream, JanetBuffer *buf, int32_t nbytes, int flags);
|
||||||
|
JANET_API void janet_ev_connect(JanetStream *stream, int flags);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Write async to a stream */
|
/* Write async to a stream */
|
||||||
|
@ -333,4 +333,29 @@
|
|||||||
|
|
||||||
(assert (pos? (length (gensym))) "gensym not empty, regression #753")
|
(assert (pos? (length (gensym))) "gensym not empty, regression #753")
|
||||||
|
|
||||||
|
|
||||||
|
# os/clock. These tests might prove fragile under CI because they
|
||||||
|
# rely on measured time. We'll see.
|
||||||
|
|
||||||
|
(defmacro measure-time [clocks & body]
|
||||||
|
(def [t1 t2] [(gensym) (gensym)])
|
||||||
|
~(do
|
||||||
|
(def ,t1 (map |(os/clock $) ,clocks))
|
||||||
|
,;body
|
||||||
|
(def ,t2 (map |(os/clock $) ,clocks))
|
||||||
|
(zipcoll ,clocks (map |(- ;$) (map tuple ,t2 ,t1))))
|
||||||
|
)
|
||||||
|
|
||||||
|
# Spin for 0.1 seconds
|
||||||
|
(def dt (measure-time [:realtime :monotonic :cputime]
|
||||||
|
(def t1 (os/clock :monotonic))
|
||||||
|
(while (< (- (os/clock :monotonic) t1) 0.1) true)))
|
||||||
|
(assert (> (dt :monotonic) 0.10))
|
||||||
|
(assert (> (dt :cputime) 0.05))
|
||||||
|
|
||||||
|
# Sleep for 0.1 seconds
|
||||||
|
(def dt (measure-time [:realtime :monotonic :cputime] (os/sleep 0.1)))
|
||||||
|
(assert (> (dt :monotonic) 0.10))
|
||||||
|
(assert (< (dt :cputime) 0.05))
|
||||||
|
|
||||||
(end-suite)
|
(end-suite)
|
||||||
|
@ -253,4 +253,13 @@
|
|||||||
# Check missing struct proto bug.
|
# Check missing struct proto bug.
|
||||||
(assert (struct/getproto (struct/with-proto {:a 1} :b 2 :c nil)) "missing struct proto")
|
(assert (struct/getproto (struct/with-proto {:a 1} :b 2 :c nil)) "missing struct proto")
|
||||||
|
|
||||||
|
# Test thaw and freeze
|
||||||
|
(def table-to-freeze @{:c 22 :b [1 2 3 4] :d @"test" :e "test2"})
|
||||||
|
(def table-to-freeze-with-inline-proto @{:a @[1 2 3] :b @[1 2 3 4] :c 22 :d @"test" :e @"test2"})
|
||||||
|
(def struct-to-thaw (struct/with-proto {:a [1 2 3]} :c 22 :b [1 2 3 4] :d "test" :e "test2"))
|
||||||
|
(table/setproto table-to-freeze @{:a @[1 2 3]})
|
||||||
|
(assert (deep= {:a [1 2 3] :b [1 2 3 4] :c 22 :d "test" :e "test2"} (freeze table-to-freeze)))
|
||||||
|
(assert (deep= table-to-freeze-with-inline-proto (thaw table-to-freeze)))
|
||||||
|
(assert (deep= table-to-freeze-with-inline-proto (thaw struct-to-thaw)))
|
||||||
|
|
||||||
(end-suite)
|
(end-suite)
|
||||||
|
Loading…
Reference in New Issue
Block a user