mirror of
https://github.com/libuv/libuv
synced 2025-03-28 21:13:16 +00:00
core: add getter/setter functions for easier ABI compat
Add getter/setter functions for the fields of public structs that might be relevant to e.g. Node.js addons. Through these methods, ABI compatibility for a subset of the ABI is easier to achieve, since using them makes code independent of the exact offsets of these fields. The intended use case that prompted this are N-API addons for Node.js, which look for more long-term ABI compatibility guarantees than typical Node code. With these helper functions, using libuv directly should no longer be an obstacle for such addons. PR-URL: https://github.com/libuv/libuv/pull/1657 Refs: https://github.com/nodejs/node/issues/13512 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Refael Ackermann <refack@gmail.com> Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
This commit is contained in:
parent
c6b7e19f81
commit
0d6525acae
@ -29,6 +29,7 @@ libuv_la_SOURCES = src/fs-poll.c \
|
||||
src/inet.c \
|
||||
src/queue.h \
|
||||
src/threadpool.c \
|
||||
src/uv-data-getter-setters.c \
|
||||
src/uv-common.c \
|
||||
src/uv-common.h \
|
||||
src/version.c
|
||||
@ -174,6 +175,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
|
||||
test/test-fs-poll.c \
|
||||
test/test-fs.c \
|
||||
test/test-fork.c \
|
||||
test/test-getters-setters.c \
|
||||
test/test-get-currentexe.c \
|
||||
test/test-get-loadavg.c \
|
||||
test/test-get-memory.c \
|
||||
|
@ -53,6 +53,7 @@ src/unix/tty.c
|
||||
src/unix/udp.c
|
||||
src/uv-common.c
|
||||
src/uv-common.h
|
||||
src/uv-data-getter-setters.c
|
||||
"
|
||||
|
||||
TESTS="
|
||||
@ -100,6 +101,7 @@ test/test-fs-copyfile.c
|
||||
test/test-fs-event.c
|
||||
test/test-fs-poll.c
|
||||
test/test-fs.c
|
||||
test/test-getters-setters.c
|
||||
test/test-get-currentexe.c
|
||||
test/test-get-loadavg.c
|
||||
test/test-get-memory.c
|
||||
|
@ -340,6 +340,36 @@ API
|
||||
.. note::
|
||||
These functions are not implemented on Windows.
|
||||
|
||||
.. c:function:: uv_fs_type uv_fs_get_type(const uv_fs_t* req)
|
||||
|
||||
Returns `req->fs_type`.
|
||||
|
||||
.. versionadded:: 1.19.0
|
||||
|
||||
.. c:function:: ssize_t uv_fs_get_result(const uv_fs_t* req)
|
||||
|
||||
Returns `req->result`.
|
||||
|
||||
.. versionadded:: 1.19.0
|
||||
|
||||
.. c:function:: void* uv_fs_get_ptr(const uv_fs_t* req)
|
||||
|
||||
Returns `req->ptr`.
|
||||
|
||||
.. versionadded:: 1.19.0
|
||||
|
||||
.. c:function:: const char* uv_fs_get_path(const uv_fs_t* req)
|
||||
|
||||
Returns `req->path`.
|
||||
|
||||
.. versionadded:: 1.19.0
|
||||
|
||||
.. c:function:: uv_stat_t* uv_fs_get_statbuf(uv_fs_t* req)
|
||||
|
||||
Returns `&req->statbuf`.
|
||||
|
||||
.. versionadded:: 1.19.0
|
||||
|
||||
.. seealso:: The :c:type:`uv_req_t` API functions also apply.
|
||||
|
||||
Helper functions
|
||||
|
@ -211,6 +211,38 @@ just for some handle types.
|
||||
Be very careful when using this function. libuv assumes it's in control of the file
|
||||
descriptor so any change to it may lead to malfunction.
|
||||
|
||||
.. c:function:: uv_loop_t* uv_handle_get_loop(const uv_handle_t* handle)
|
||||
|
||||
Returns `handle->loop`.
|
||||
|
||||
.. versionadded:: 1.19.0
|
||||
|
||||
.. c:function:: void* uv_handle_get_data(const uv_handle_t* handle)
|
||||
|
||||
Returns `handle->data`.
|
||||
|
||||
.. versionadded:: 1.19.0
|
||||
|
||||
.. c:function:: void* uv_handle_set_data(uv_handle_t* handle, void* data)
|
||||
|
||||
Sets `handle->data` to `data`.
|
||||
|
||||
.. versionadded:: 1.19.0
|
||||
|
||||
.. c:function:: uv_handle_type uv_handle_get_type(const uv_handle_t* handle)
|
||||
|
||||
Returns `handle->type`.
|
||||
|
||||
.. versionadded:: 1.19.0
|
||||
|
||||
.. c:function:: const char* uv_handle_type_name(uv_handle_type type)
|
||||
|
||||
Returns the name for the equivalent struct for a given handle type,
|
||||
e.g. `"pipe"` (as in :c:type:`uv_pipe_t`) for `UV_NAMED_PIPE`.
|
||||
|
||||
If no such handle type exists, this returns `NULL`.
|
||||
|
||||
.. versionadded:: 1.19.0
|
||||
|
||||
.. _refcount:
|
||||
|
||||
|
@ -222,3 +222,15 @@ API
|
||||
Any previous value returned from :c:func`uv_backend_fd` is now
|
||||
invalid. That function must be called again to determine the
|
||||
correct backend file descriptor.
|
||||
|
||||
.. c:function:: void* uv_loop_get_data(const uv_loop_t* loop)
|
||||
|
||||
Returns `loop->data`.
|
||||
|
||||
.. versionadded:: 1.19.0
|
||||
|
||||
.. c:function:: void* uv_loop_set_data(uv_loop_t* loop, void* data)
|
||||
|
||||
Sets `loop->data` to `data`.
|
||||
|
||||
.. versionadded:: 1.19.0
|
||||
|
@ -222,4 +222,10 @@ API
|
||||
Sends the specified signal to the given PID. Check the documentation
|
||||
on :c:ref:`signal` for signal support, specially on Windows.
|
||||
|
||||
.. c:function:: uv_pid_t uv_process_get_pid(const uv_process_t* handle)
|
||||
|
||||
Returns `handle->pid`.
|
||||
|
||||
.. versionadded:: 1.19.0
|
||||
|
||||
.. seealso:: The :c:type:`uv_handle_t` API functions also apply.
|
||||
|
@ -80,3 +80,30 @@ API
|
||||
|
||||
Returns the size of the given request type. Useful for FFI binding writers
|
||||
who don't want to know the structure layout.
|
||||
|
||||
.. c:function:: void* uv_req_get_data(const uv_req_t* req)
|
||||
|
||||
Returns `req->data`.
|
||||
|
||||
.. versionadded:: 1.19.0
|
||||
|
||||
.. c:function:: void* uv_req_set_data(uv_req_t* req, void* data)
|
||||
|
||||
Sets `req->data` to `data`.
|
||||
|
||||
.. versionadded:: 1.19.0
|
||||
|
||||
.. c:function:: uv_req_type uv_req_get_type(const uv_req_t* req)
|
||||
|
||||
Returns `req->type`.
|
||||
|
||||
.. versionadded:: 1.19.0
|
||||
|
||||
.. c:function:: const char* uv_req_type_name(uv_req_type type)
|
||||
|
||||
Returns the name for the equivalent struct for a given request type,
|
||||
e.g. `"connect"` (as in :c:type:`uv_connect_t`) for `UV_CONNECT`.
|
||||
|
||||
If no such request type exists, this returns `NULL`.
|
||||
|
||||
.. versionadded:: 1.19.0
|
||||
|
@ -228,4 +228,10 @@ API
|
||||
|
||||
.. versionchanged:: 1.4.0 UNIX implementation added.
|
||||
|
||||
.. c:function:: size_t uv_stream_get_write_queue_size(const uv_stream_t* stream)
|
||||
|
||||
Returns `stream->write_queue_size`.
|
||||
|
||||
.. versionadded:: 1.19.0
|
||||
|
||||
.. seealso:: The :c:type:`uv_handle_t` API functions also apply.
|
||||
|
@ -292,4 +292,16 @@ API
|
||||
|
||||
:returns: 0 on success, or an error code < 0 on failure.
|
||||
|
||||
.. c:function:: size_t uv_udp_get_send_queue_size(const uv_udp_t* handle)
|
||||
|
||||
Returns `handle->send_queue_size`.
|
||||
|
||||
.. versionadded:: 1.19.0
|
||||
|
||||
.. c:function:: size_t uv_udp_get_send_queue_count(const uv_udp_t* handle)
|
||||
|
||||
Returns `handle->send_queue_count`.
|
||||
|
||||
.. versionadded:: 1.19.0
|
||||
|
||||
.. seealso:: The :c:type:`uv_handle_t` API functions also apply.
|
||||
|
23
include/uv.h
23
include/uv.h
@ -425,7 +425,17 @@ struct uv_handle_s {
|
||||
};
|
||||
|
||||
UV_EXTERN size_t uv_handle_size(uv_handle_type type);
|
||||
UV_EXTERN uv_handle_type uv_handle_get_type(const uv_handle_t* handle);
|
||||
UV_EXTERN const char* uv_handle_type_name(uv_handle_type type);
|
||||
UV_EXTERN void* uv_handle_get_data(const uv_handle_t* handle);
|
||||
UV_EXTERN uv_loop_t* uv_handle_get_loop(const uv_handle_t* handle);
|
||||
UV_EXTERN void uv_handle_set_data(uv_handle_t* handle, void* data);
|
||||
|
||||
UV_EXTERN size_t uv_req_size(uv_req_type type);
|
||||
UV_EXTERN void* uv_req_get_data(const uv_req_t* req);
|
||||
UV_EXTERN void uv_req_set_data(uv_req_t* req, void* data);
|
||||
UV_EXTERN uv_req_type uv_req_get_type(const uv_req_t* req);
|
||||
UV_EXTERN const char* uv_req_type_name(uv_req_type type);
|
||||
|
||||
UV_EXTERN int uv_is_active(const uv_handle_t* handle);
|
||||
|
||||
@ -465,6 +475,8 @@ struct uv_stream_s {
|
||||
UV_STREAM_FIELDS
|
||||
};
|
||||
|
||||
UV_EXTERN size_t uv_stream_get_write_queue_size(const uv_stream_t* stream);
|
||||
|
||||
UV_EXTERN int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb);
|
||||
UV_EXTERN int uv_accept(uv_stream_t* server, uv_stream_t* client);
|
||||
|
||||
@ -642,6 +654,8 @@ UV_EXTERN int uv_udp_recv_start(uv_udp_t* handle,
|
||||
uv_alloc_cb alloc_cb,
|
||||
uv_udp_recv_cb recv_cb);
|
||||
UV_EXTERN int uv_udp_recv_stop(uv_udp_t* handle);
|
||||
UV_EXTERN size_t uv_udp_get_send_queue_size(const uv_udp_t* handle);
|
||||
UV_EXTERN size_t uv_udp_get_send_queue_count(const uv_udp_t* handle);
|
||||
|
||||
|
||||
/*
|
||||
@ -962,6 +976,7 @@ UV_EXTERN int uv_spawn(uv_loop_t* loop,
|
||||
const uv_process_options_t* options);
|
||||
UV_EXTERN int uv_process_kill(uv_process_t*, int signum);
|
||||
UV_EXTERN int uv_kill(int pid, int signum);
|
||||
UV_EXTERN uv_pid_t uv_process_get_pid(const uv_process_t*);
|
||||
|
||||
|
||||
/*
|
||||
@ -1135,6 +1150,12 @@ struct uv_fs_s {
|
||||
UV_FS_PRIVATE_FIELDS
|
||||
};
|
||||
|
||||
UV_EXTERN uv_fs_type uv_fs_get_type(const uv_fs_t*);
|
||||
UV_EXTERN ssize_t uv_fs_get_result(const uv_fs_t*);
|
||||
UV_EXTERN void* uv_fs_get_ptr(const uv_fs_t*);
|
||||
UV_EXTERN const char* uv_fs_get_path(const uv_fs_t*);
|
||||
UV_EXTERN uv_stat_t* uv_fs_get_statbuf(uv_fs_t*);
|
||||
|
||||
UV_EXTERN void uv_fs_req_cleanup(uv_fs_t* req);
|
||||
UV_EXTERN int uv_fs_close(uv_loop_t* loop,
|
||||
uv_fs_t* req,
|
||||
@ -1516,6 +1537,8 @@ struct uv_loop_s {
|
||||
UV_LOOP_PRIVATE_FIELDS
|
||||
};
|
||||
|
||||
UV_EXTERN void* uv_loop_get_data(const uv_loop_t*);
|
||||
UV_EXTERN void uv_loop_set_data(uv_loop_t*, void* data);
|
||||
|
||||
/* Don't export the private CPP symbols. */
|
||||
#undef UV_HANDLE_TYPE_PRIVATE
|
||||
|
96
src/uv-data-getter-setters.c
Normal file
96
src/uv-data-getter-setters.c
Normal file
@ -0,0 +1,96 @@
|
||||
#include "uv.h"
|
||||
|
||||
const char* uv_handle_type_name(uv_handle_type type) {
|
||||
switch (type) {
|
||||
#define XX(uc,lc) case UV_##uc: return #lc;
|
||||
UV_HANDLE_TYPE_MAP(XX)
|
||||
#undef XX
|
||||
case UV_FILE: return "file";
|
||||
case UV_HANDLE_TYPE_MAX:
|
||||
case UV_UNKNOWN_HANDLE: return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uv_handle_type uv_handle_get_type(const uv_handle_t* handle) {
|
||||
return handle->type;
|
||||
}
|
||||
|
||||
void* uv_handle_get_data(const uv_handle_t* handle) {
|
||||
return handle->data;
|
||||
}
|
||||
|
||||
uv_loop_t* uv_handle_get_loop(const uv_handle_t* handle) {
|
||||
return handle->loop;
|
||||
}
|
||||
|
||||
void uv_handle_set_data(uv_handle_t* handle, void* data) {
|
||||
handle->data = data;
|
||||
}
|
||||
|
||||
const char* uv_req_type_name(uv_req_type type) {
|
||||
switch (type) {
|
||||
#define XX(uc,lc) case UV_##uc: return #lc;
|
||||
UV_REQ_TYPE_MAP(XX)
|
||||
#undef XX
|
||||
case UV_REQ_TYPE_MAX:
|
||||
case UV_UNKNOWN_REQ: return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uv_req_type uv_req_get_type(const uv_req_t* req) {
|
||||
return req->type;
|
||||
}
|
||||
|
||||
void* uv_req_get_data(const uv_req_t* req) {
|
||||
return req->data;
|
||||
}
|
||||
|
||||
void uv_req_set_data(uv_req_t* req, void* data) {
|
||||
req->data = data;
|
||||
}
|
||||
|
||||
size_t uv_stream_get_write_queue_size(const uv_stream_t* stream) {
|
||||
return stream->write_queue_size;
|
||||
}
|
||||
|
||||
size_t uv_udp_get_send_queue_size(const uv_udp_t* handle) {
|
||||
return handle->send_queue_size;
|
||||
}
|
||||
|
||||
size_t uv_udp_get_send_queue_count(const uv_udp_t* handle) {
|
||||
return handle->send_queue_count;
|
||||
}
|
||||
|
||||
uv_pid_t uv_process_get_pid(const uv_process_t* proc) {
|
||||
return proc->pid;
|
||||
}
|
||||
|
||||
uv_fs_type uv_fs_get_type(const uv_fs_t* req) {
|
||||
return req->fs_type;
|
||||
}
|
||||
|
||||
ssize_t uv_fs_get_result(const uv_fs_t* req) {
|
||||
return req->result;
|
||||
}
|
||||
|
||||
void* uv_fs_get_ptr(const uv_fs_t* req) {
|
||||
return req->ptr;
|
||||
}
|
||||
|
||||
const char* uv_fs_get_path(const uv_fs_t* req) {
|
||||
return req->path;
|
||||
}
|
||||
|
||||
uv_stat_t* uv_fs_get_statbuf(uv_fs_t* req) {
|
||||
return &req->statbuf;
|
||||
}
|
||||
|
||||
void* uv_loop_get_data(const uv_loop_t* loop) {
|
||||
return loop->data;
|
||||
}
|
||||
|
||||
void uv_loop_set_data(uv_loop_t* loop, void* data) {
|
||||
loop->data = data;
|
||||
}
|
88
test/test-getters-setters.c
Normal file
88
test/test-getters-setters.c
Normal file
@ -0,0 +1,88 @@
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
int cookie1;
|
||||
int cookie2;
|
||||
int cookie3;
|
||||
|
||||
|
||||
TEST_IMPL(handle_type_name) {
|
||||
ASSERT(strcmp(uv_handle_type_name(UV_NAMED_PIPE), "pipe") == 0);
|
||||
ASSERT(strcmp(uv_handle_type_name(UV_UDP), "udp") == 0);
|
||||
ASSERT(strcmp(uv_handle_type_name(UV_FILE), "file") == 0);
|
||||
ASSERT(uv_handle_type_name(UV_HANDLE_TYPE_MAX) == NULL);
|
||||
ASSERT(uv_handle_type_name(UV_HANDLE_TYPE_MAX + 1) == NULL);
|
||||
ASSERT(uv_handle_type_name(UV_UNKNOWN_HANDLE) == NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(req_type_name) {
|
||||
ASSERT(strcmp(uv_req_type_name(UV_REQ), "req") == 0);
|
||||
ASSERT(strcmp(uv_req_type_name(UV_UDP_SEND), "udp_send") == 0);
|
||||
ASSERT(strcmp(uv_req_type_name(UV_WORK), "work") == 0);
|
||||
ASSERT(uv_req_type_name(UV_REQ_TYPE_MAX) == NULL);
|
||||
ASSERT(uv_req_type_name(UV_REQ_TYPE_MAX + 1) == NULL);
|
||||
ASSERT(uv_req_type_name(UV_UNKNOWN_REQ) == NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(getters_setters) {
|
||||
uv_loop_t* loop;
|
||||
uv_pipe_t* pipe;
|
||||
uv_fs_t* fs;
|
||||
int r;
|
||||
|
||||
loop = malloc(uv_loop_size());
|
||||
ASSERT(loop != NULL);
|
||||
r = uv_loop_init(loop);
|
||||
ASSERT(r == 0);
|
||||
|
||||
uv_loop_set_data(loop, &cookie1);
|
||||
ASSERT(loop->data == &cookie1);
|
||||
ASSERT(uv_loop_get_data(loop) == &cookie1);
|
||||
|
||||
pipe = malloc(uv_handle_size(UV_NAMED_PIPE));
|
||||
r = uv_pipe_init(loop, pipe, 0);
|
||||
ASSERT(uv_handle_get_type((uv_handle_t*)pipe) == UV_NAMED_PIPE);
|
||||
|
||||
ASSERT(uv_handle_get_loop((uv_handle_t*)pipe) == loop);
|
||||
pipe->data = &cookie2;
|
||||
ASSERT(uv_handle_get_data((uv_handle_t*)pipe) == &cookie2);
|
||||
uv_handle_set_data((uv_handle_t*)pipe, &cookie1);
|
||||
ASSERT(uv_handle_get_data((uv_handle_t*)pipe) == &cookie1);
|
||||
ASSERT(pipe->data == &cookie1);
|
||||
|
||||
ASSERT(uv_stream_get_write_queue_size((uv_stream_t*)pipe) == 0);
|
||||
pipe->write_queue_size++;
|
||||
ASSERT(uv_stream_get_write_queue_size((uv_stream_t*)pipe) == 1);
|
||||
pipe->write_queue_size--;
|
||||
uv_close((uv_handle_t*)pipe, NULL);
|
||||
|
||||
r = uv_run(loop, UV_RUN_DEFAULT);
|
||||
ASSERT(r == 0);
|
||||
|
||||
fs = malloc(uv_req_size(UV_FS));
|
||||
uv_fs_stat(loop, fs, ".", NULL);
|
||||
|
||||
r = uv_run(loop, UV_RUN_DEFAULT);
|
||||
ASSERT(r == 0);
|
||||
|
||||
ASSERT(uv_fs_get_type(fs) == UV_FS_STAT);
|
||||
ASSERT(uv_fs_get_result(fs) == 0);
|
||||
ASSERT(uv_fs_get_ptr(fs) == uv_fs_get_statbuf(fs));
|
||||
ASSERT(uv_fs_get_statbuf(fs)->st_mode & S_IFDIR);
|
||||
ASSERT(strcmp(uv_fs_get_path(fs), ".") == 0);
|
||||
uv_fs_req_cleanup(fs);
|
||||
|
||||
r = uv_loop_close(loop);
|
||||
ASSERT(r == 0);
|
||||
|
||||
free(pipe);
|
||||
free(fs);
|
||||
free(loop);
|
||||
return 0;
|
||||
}
|
@ -397,6 +397,10 @@ HELPER_DECLARE (pipe_echo_server)
|
||||
|
||||
TEST_DECLARE (queue_foreach_delete)
|
||||
|
||||
TEST_DECLARE (handle_type_name)
|
||||
TEST_DECLARE (req_type_name)
|
||||
TEST_DECLARE (getters_setters)
|
||||
|
||||
#ifndef _WIN32
|
||||
TEST_DECLARE (fork_timer)
|
||||
TEST_DECLARE (fork_socketpair)
|
||||
@ -870,6 +874,10 @@ TASK_LIST_START
|
||||
|
||||
TEST_ENTRY (queue_foreach_delete)
|
||||
|
||||
TEST_ENTRY (handle_type_name)
|
||||
TEST_ENTRY (req_type_name)
|
||||
TEST_ENTRY (getters_setters)
|
||||
|
||||
#ifndef _WIN32
|
||||
TEST_ENTRY (fork_timer)
|
||||
TEST_ENTRY (fork_socketpair)
|
||||
|
@ -805,6 +805,8 @@ TEST_IMPL(spawn_detached) {
|
||||
|
||||
ASSERT(exit_cb_called == 0);
|
||||
|
||||
ASSERT(process.pid == uv_process_get_pid(&process));
|
||||
|
||||
r = uv_kill(process.pid, 0);
|
||||
ASSERT(r == 0);
|
||||
|
||||
|
2
uv.gyp
2
uv.gyp
@ -78,6 +78,7 @@
|
||||
'src/inet.c',
|
||||
'src/queue.h',
|
||||
'src/threadpool.c',
|
||||
'src/uv-data-getter-setters.c',
|
||||
'src/uv-common.c',
|
||||
'src/uv-common.h',
|
||||
'src/version.c'
|
||||
@ -380,6 +381,7 @@
|
||||
'test/test-fs.c',
|
||||
'test/test-fs-copyfile.c',
|
||||
'test/test-fs-event.c',
|
||||
'test/test-getters-setters.c',
|
||||
'test/test-get-currentexe.c',
|
||||
'test/test-get-memory.c',
|
||||
'test/test-get-passwd.c',
|
||||
|
Loading…
x
Reference in New Issue
Block a user