假设 pid_t 始终是 int 类型(如标准中所定义)是否安全?

Is it safe to assume pid_t is always an int type (as defined in the standard)?

我想自动比较和交换 pid_t 变量。我在标准中读到它是 int 类型。

我知道 atomic_compare_exchange_strong_explicit() 可以自行管理事情。我需要做的就是将类型设置为 _Atomic(pid_t).

但是因为我在 macOS 上工作,我想让它与 OSX 旧库兼容,也就是 libkern/OSAtomic.h 需要知道 CAS 类型的类型和大小它。

就像 size_t 我可以简单地做,

#   ifdef __LP64__
#       define CAS_size_t(old, new, mem) \
        OSAtomicCompareAndSwap64((int64_t) (*old), (int64_t) (new), (volatile int64_t *) (mem))
#   else
#       define CAS_size_t(old, new, mem) \
        OSAtomicCompareAndSwap32((int32_t) (*old), (int32_t) (new), (volatile int32_t *) (mem))
#   endif

但如果是 pid_t 我不确定,因为即使 __LP64__ 没有定义,它也可以是 int64_t、int32_t、int16_t还是什么?

只需检查宏中值的大小:

#define OSAtomicCompareAndSwap(old, new, mem)  do{ \
     if (sizeof(*old) == sizeof(int32_t)) { \
        OSAtomicCompareAndSwap32((int32_t)(*old), (int32_t) (new), (volatile int32_t *) (mem));  \
     } else if (sizeof(*old) == sizeof(int64_t)) { \
        OSAtomicCompareAndSwap64((int64_t)(*old), (int64_t) (new), (volatile int64_t *) (mem));  \
     } else assert(0); }while(0)

无论如何,编译器应该优化这些检查。它不是类型检查(为此我们需要 C++-ish typeid),只检查大小。

如果您需要 return 一个值,如果您认为您需要传递另一个变量:

#define OSAtomicCompareAndSwap(ret, old, new, mem)  do{ \
     if (sizeof(*old) == sizeof(int32_t)) { \
        ret = OSAtomicCompareAndSwap32((int32_t)(*old), (int32_t) (new), (volatile int32_t *) (mem));  \
     } else if (sizeof(*old) == sizeof(int64_t)) { \
        ret = OSAtomicCompareAndSwap64((int64_t)(*old), (int64_t) (new), (volatile int64_t *) (mem));  \
     } else assert(0); }while(0)

或前。将指向变量的指针传递给 memcpy-ied 以及结果等。或者您可以使用 statement expression gcc 扩展。

语句表达式可能如下所示:

#define OSAtomicCompareAndSwap(old, new, mem)  __extension__({ \
     int64_t ret = 0; \
     if (sizeof(*old) == sizeof(int32_t)) { \
        ret = OSAtomicCompareAndSwap32((int32_t)(*old), (int32_t) (new), (volatile int32_t *) (mem));  \
     } else if (sizeof(*old) == sizeof(int64_t)) { \
        ret = OSAtomicCompareAndSwap64((int64_t)(*old), (int64_t) (new), (volatile int64_t *) (mem));  \
     } else { \
          assert(0); \
     } \
     ret; \
})