Можно ли предположить, что pid_t всегда является типом int (как определено в стандарте)? - PullRequest
1 голос
/ 28 мая 2019

Я хотел атомарно сравнить и поменять местами переменную 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 или что-то?

1 Ответ

3 голосов
/ 28 мая 2019

Просто проверьте размер значения внутри макроса:

#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), проверяется только размер.

Если вам нужно вернуть значение, если вам нужно передать другую переменную:

#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)

или отл. передать указатель на переменную, которая будет связана с результатом или чем-то подобным. Или вы можете использовать выражение выражения расширение 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; \
})
...