gpt4 book ai didi

c - 使用 pthread 实现 errno 模拟

转载 作者:太空宇宙 更新时间:2023-11-04 02:05:27 24 4
gpt4 key购买 nike

正如 $ man errno 所说,“errno 由 ISO C 标准定义为 int 类型的可修改左值,不能显式声明;errno 可以是宏。errno 是线程-local;在一个线程中设置它不会影响它在任何其他线程中的值。”

我正在开发一个 C 库,它可以在 POSIX 和 Windows 中工作,所以我决定坚持使用 errnoGetLastError/SetLastError自己的错误类型。我的每个函数都将错误代码作为 cg_error 对象返回,其中 cg_error 只是一个 typedef。但是,对于自定义分配器等某些函数,最好还是使用 errno 之类的东西,但使用我自己的 cg_error 类型。


glibc 中的 AFAIK errno 是这样实现的:

#define errno (*__errno_location ())


我正在尝试在 Linux 上使用 pthreads 并在 Windows 上使用 TlsAlloc 和 friend 实现类似的功能。这是我现在拥有的(但只有 POSIX,似乎是在 Web 上找到的文章 “线程特定存储模式” 中的 Solaris 实现):

cg_error * CG_ERRNO_TLS(void)
{
#if CG_FEATURE_POSIX
static int once;
static pthread_key_t key;
static pthread_mutex_t lock;
cg_error * error = NULL;
if (once)
{
pthread_mutex_lock(&lock);
if (once)
{
(void) pthread_key_create(&key, cg_free);
once = 1;
}
pthread_mutex_unlock(&lock);
}
error = pthread_getspecific(key);
if (!error)
{
error = cg_malloc(sizeof(*error));
(void) pthread_setspecific(key, error);
}
return error;
#endif
}

#define cg_errno (*CG_ERRNO_TLS())

但是,当我试图设置或获取cg_errno时,它的int值是6344768,这不是我想要的。我究竟做错了什么?定义类似 errno 的正确方法是什么?提前致谢!


P.S. 我知道我可以使用 __thread__declspec(thread),但这些东西是特定于编译器的(也可能是系统特定的) ; 我听说 __thread 不工作,例如对于带有 gcc 的 MacOSX)。

P.P.S. cg_error 的基值为 CG_ERROR_NONE,始终为 0。



更新:

#if CG_FEATURE_POSIX
static pthread_key_t cg_errno_key;
static pthread_once_t cg_errno_once = PTHREAD_ONCE_INIT;


static void cg_errno_init(void)
{ (void) pthread_key_create(&cg_errno_key, cg_free); }


cg_error * cg_errno_storage(void)
{
cg_error * error = NULL;
(void) pthread_once(&cg_errno_once, cg_errno_init);
error = pthread_getspecific(cg_errno_key);
if (!error)
{
error = cg_malloc(sizeof(*error));
(void) pthread_setspecific(cg_errno_key, error);
}
return error;
}

#define cg_errno (*cg_errno_storage())
#endif

最佳答案

您在 once 上的条件是错误的。它应该是 !once

但是使用 int 并不能保证有效。有一个特殊类型 pthread_once_t 具有函数 pthread_once 用于您要实现的任务。

另外,lock 应该有一个初始化器,PTHREAD_MUTEX_INITIALIZER

pthread_once_t 的使用如下所示:

static pthread_key_t key;
static pthread_once_t once = PTHREAD_ONCE_INIT;

static
void init_error_key_once(void) {
pthread_key_create(&key, cg_free);
}

cg_error * CG_ERRNO_TLS_POSIX(void)
{
cg_error * error = NULL;
pthread_once(&once, init_error_key_once);
...

}

关于c - 使用 pthread 实现 errno 模拟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21137835/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com