简体   繁体   English

使用未声明的标识符 'PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP'

[英]Use of undeclared identifier 'PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP'

I'm trying to compile using gcc on macOS 10.14 with gcc in the Terminal.我正在尝试在 macOS 10.14 上使用 gcc 进行编译,并在终端中使用 gcc。

I've included #define _GNU_SOURCE at the top of my C program, and #include <pthread.h>我在 C 程序的顶部包含了#define _GNU_SOURCE#include <pthread.h>

But when I use the following: gcc input.c -o output -lpthread or -pthread I get the following error.但是当我使用以下内容时: gcc input.c -o output -lpthread-pthread我收到以下错误。 I've also tried with -std=c99 :我也试过-std=c99

input.c:50:33: error: use of undeclared identifier
'PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP'
pthread_mutex_t request_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;

Here's a summary of my code:这是我的代码的摘要:

input.c:输入.c:

#define _GNU_SOURCE
#include <stdlib.h>
…
#include <pthread.h>

pthread_mutex_t request_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;

int main(int argc, char* argv[])
{
  ...
}

Edit编辑

I was able to get the code working by removing _NP at the end of PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP .我能够通过删除PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP末尾的_NP来使代码工作。 Thanks for everyone's suggestions.谢谢大家的建议。

PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP is a non-standard extension, and evidently MacOS doesn't support it. PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP是一个非标准扩展,显然 MacOS 不支持它。

You should instead initialise your mutex at the beginning of main() :你应该在main()的开头初始化你的互斥锁:

#include <stdio.h>
#include <string.h>
#include <pthread.h>

pthread_mutex_t request_mutex;

int init_recursive_mutex(pthread_mutex_t *mutex)
{
    pthread_mutexattr_t attr;
    int r;

    r = pthread_mutexattr_init(&attr);
    if (r != 0)
        return r;

    r = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);

    if (r == 0)
        r = pthread_mutex_init(mutex, &attr);

    pthread_mutexattr_destroy(&attr);

    return r;
}

int main(int argc, char* argv[])
{
    int r;

    r = init_recursive_mutex(&request_mutex);
    if (r != 0)
    {
        fprintf(stderr, "Failed to initialise request_mutex: %s\n", strerror(r));
        return 1;
    }

    /* ... */
}

_GNU_SOURCE will not do anything to reveal library extensions on Mac OS, because Mac OS isn't from the GNU project and doesn't use the GNU C library. _GNU_SOURCE不会显示 Mac OS 上的库扩展,因为 Mac OS 不是来自 GNU 项目并且不使用 GNU C 库。

On Mac OS, the "reveal extensions" feature selection macro is _DARWIN_C_SOURCE .在 Mac OS 上,“显示扩展”功能选择宏是_DARWIN_C_SOURCE

However, this will not necessarily reveal a PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ;但是,这不一定会显示PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP I don't think it exists.我不认为它存在。 Of course, the recursive mutex type PTHREAD_MUTEX_RECURSIVE exists;当然,递归互斥类型PTHREAD_MUTEX_RECURSIVE存在的; only there is no initializer to set one up statically.只有没有初始化程序来静态设置一个。 The code will have to be ported to explicitly call pthread_mutex_init to initialize its recursive mutexes.必须移植代码以显式调用pthread_mutex_init来初始化其递归互斥锁。

Another idea is to just write code that doesn't require recursive mutexes.另一个想法是只编写不需要递归互斥锁的代码。 Recursive mutexes are for "scatter brained" concurrent programming.递归互斥锁用于“分散大脑”并发编程。 "Well, I don't know whether I already have this lock or not, so I will grab it just in case." “嗯,我不知道我有没有这把锁,所以我会抓住它以防万一。” The sane alternative is to design the program so that you know!明智的选择是设计程序,以便您知道!

Recursive mutexes are essentially a band-aid solution for certain situations that arise when when legacy single-threaded code is being converted to multithreading.递归互斥锁本质上是一种创可贴解决方案,适用于在将遗留单线程代码转换为多线程时出现的某些情况。 Recursive mutexes are out of place in a completely new design.递归互斥锁在全新的设计中是不合适的。

If you avoid recursive mutexes, you can use the standard PTHREAD_MUTEX_INITIALIZER .如果你避免递归互斥,你可以使用标准的PTHREAD_MUTEX_INITIALIZER

PTHREAD_RECURSIVE_MUTEX_INITIALIZER is available on OSX, but only starting from 10.7, so if you have to support earlier versions, you have to either initialize mutex directly before use (like @caf suggested in this answer ) or initialize it lazily using pthread_once : PTHREAD_RECURSIVE_MUTEX_INITIALIZER在 OSX 上可用,但仅从 10.7 开始,因此如果您必须支持早期版本,则必须在使用前直接初始化互斥锁(如本答案中建议的@caf)或使用pthread_once延迟初始化:

#if ((__MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) || (__IPHONE_OS_VERSION_MIN_REQUIRED && __IPHONE_OS_VERSION_MIN_REQUIRED >= 50000)) || defined(__DRIVERKIT_VERSION_MIN_REQUIRED)

static pthread_mutex_t s_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER;

int lock() {
  return pthread_mutex_lock(&s_mutex);
}

int unlock() {
  return pthread_mutex_unlock(&s_mutex);
}

#else

static pthread_mutex_t s_mutex;
static pthread_once_t s_mutex_init = PTHREAD_ONCE_INIT;

static void init_mutex() {
  init_recursive_mutex(&s_mutex);
} 

int lock() {
  pthread_once(&s_mutex_init, init_mutex);
  return pthread_mutex_lock(&s_mutex);
} 

int unlock() {
  return pthread_mutex_unlock(&s_mutex);
}

#endif

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM