如何知道句柄是否已经初始化
How to know if a handle has been already initialized
libuv
中的句柄在使用前必须初始化。
它们都有一个关联的 uv_<handle>_init
函数。例如,uv_timer_t
有一个关联函数 uv_timer_init
来初始化它。
也就是说,我注意到如果我多次调用给定句柄的 init 函数,libuv
会出现未定义的行为。
一旦我关闭循环并执行一堆无效的 read/write 操作,它就会显示问题。
有没有办法知道句柄是否已经初始化?
例如,要知道句柄是关闭还是关闭,存在函数uv_is_closing
.
有没有类似的函数可以知道句柄是否已经初始化?
与 uv_is_closing
的比较不太合适。 Closing 可以在你调用它的时候设置一点,你可以稍后检查。但是,当还没有函数接触到句柄时,您希望检查什么?
不过,还是有变通办法的:
标记未初始化的句柄
明确将您的句柄归零:memset(&handle, 0x00, sizeof handle)
。要查明句柄是否未初始化,请检查它是否仍为全字节零:
int is_all_zeroes(void *buf, size_t len) {
for (unsigned char *p = buf; p < buf + len; p++) {
if (*p != 0x00)
return 0;
}
return 1;
}
这 假设全零句柄不能是有效对象 ,这是一个安全的赌注,因为任何初始化的 libuv 句柄都将包含非空指针,这不太可能以后有变化。
标记初始化句柄
如果我们不标记未初始化的对象,我们将不得不标记已初始化的对象。
保留已初始化句柄的列表。 Add/remove 个条目,就像你 initialize/close 个一样。
在内部,libuv 确实已经标记了已初始化的句柄。句柄初始化后,它会添加到 uv_loop_t
特定的 QUEUE
.
此 API 不打算公开 但是:
#define uv__handle_init(loop_, h, type_) \
do { \
(h)->loop = (loop_); \
(h)->type = (type_); \
(h)->flags = UV__HANDLE_REF; /* Ref the loop when active. */ \
QUEUE_INSERT_TAIL(&(loop_)->handle_queue, &(h)->handle_queue); \
uv__handle_platform_init(h); \
} \
所以你最好自己跟踪它。
按照建议 here(实际上是 libev
的文档,但建议也适用于 libuv
):
If you need more data and don't want to allocate memory separately and store a pointer to it in that data member, you can also "subclass" the watcher type and provide your own data:
struct my_io {
ev_io io;
int otherfd;
void *somedata;
struct whatever *mostinteresting;
};
// ...
struct my_io w;
ev_io_init (&w.io, my_cb, fd, EV_READ);
And since your callback will be called with a pointer to the watcher, you can cast it back to your own type:
static void my_cb (struct ev_loop *loop, ev_io *w_, int revents) {
struct my_io *w = (struct my_io *)w_;
// ...
}
使用类似的方法,我们可以定义一个具有布尔参数的新结构,该参数指示它是否已被初始化。
在创建过程中将其设置为 false(工厂方法可以在此处提供帮助)并在初始化后将其切换为 true。
初始化句柄的句柄类型与 UV_UNKNOWN_HANDLE
不同,因此可以使用以下方法:
if (uv_handle_get_type(handle) != UV_UNKNOWN_HANDLE) {
...
}
或者,甚至可能
if (uv_handle_type_name(uv_handle_get_type(handle)) != NULL) {
...
}
因为这将检查 libuv.
是否知道相关句柄的类型
libuv
中的句柄在使用前必须初始化。
它们都有一个关联的 uv_<handle>_init
函数。例如,uv_timer_t
有一个关联函数 uv_timer_init
来初始化它。
也就是说,我注意到如果我多次调用给定句柄的 init 函数,libuv
会出现未定义的行为。
一旦我关闭循环并执行一堆无效的 read/write 操作,它就会显示问题。
有没有办法知道句柄是否已经初始化?
例如,要知道句柄是关闭还是关闭,存在函数uv_is_closing
.
有没有类似的函数可以知道句柄是否已经初始化?
与 uv_is_closing
的比较不太合适。 Closing 可以在你调用它的时候设置一点,你可以稍后检查。但是,当还没有函数接触到句柄时,您希望检查什么?
不过,还是有变通办法的:
标记未初始化的句柄
明确将您的句柄归零:memset(&handle, 0x00, sizeof handle)
。要查明句柄是否未初始化,请检查它是否仍为全字节零:
int is_all_zeroes(void *buf, size_t len) {
for (unsigned char *p = buf; p < buf + len; p++) {
if (*p != 0x00)
return 0;
}
return 1;
}
这 假设全零句柄不能是有效对象 ,这是一个安全的赌注,因为任何初始化的 libuv 句柄都将包含非空指针,这不太可能以后有变化。
标记初始化句柄
如果我们不标记未初始化的对象,我们将不得不标记已初始化的对象。
保留已初始化句柄的列表。 Add/remove 个条目,就像你 initialize/close 个一样。
在内部,libuv 确实已经标记了已初始化的句柄。句柄初始化后,它会添加到 uv_loop_t
特定的 QUEUE
.
此 API 不打算公开 但是:
#define uv__handle_init(loop_, h, type_) \
do { \
(h)->loop = (loop_); \
(h)->type = (type_); \
(h)->flags = UV__HANDLE_REF; /* Ref the loop when active. */ \
QUEUE_INSERT_TAIL(&(loop_)->handle_queue, &(h)->handle_queue); \
uv__handle_platform_init(h); \
} \
所以你最好自己跟踪它。
按照建议 here(实际上是 libev
的文档,但建议也适用于 libuv
):
If you need more data and don't want to allocate memory separately and store a pointer to it in that data member, you can also "subclass" the watcher type and provide your own data:
struct my_io { ev_io io; int otherfd; void *somedata; struct whatever *mostinteresting; }; // ... struct my_io w; ev_io_init (&w.io, my_cb, fd, EV_READ);
And since your callback will be called with a pointer to the watcher, you can cast it back to your own type:
static void my_cb (struct ev_loop *loop, ev_io *w_, int revents) { struct my_io *w = (struct my_io *)w_; // ... }
使用类似的方法,我们可以定义一个具有布尔参数的新结构,该参数指示它是否已被初始化。
在创建过程中将其设置为 false(工厂方法可以在此处提供帮助)并在初始化后将其切换为 true。
初始化句柄的句柄类型与 UV_UNKNOWN_HANDLE
不同,因此可以使用以下方法:
if (uv_handle_get_type(handle) != UV_UNKNOWN_HANDLE) {
...
}
或者,甚至可能
if (uv_handle_type_name(uv_handle_get_type(handle)) != NULL) {
...
}
因为这将检查 libuv.
是否知道相关句柄的类型