如何实现便携式指针比较和交换?

时间:2015-07-02 10:19:37

标签: c intrinsics

我在a StackOverflow answer中找到了compareAndSwap的代码:

boolean CompareAndSwapPointer(volatile * void * ptr,
                              void * new_value,
                              void * old_value) {
#if defined(_MSC_VER)
   if (InterlockedCompareExchange(ptr, new_value, old_value) == old_value) return false;
   else return true;
#elif (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100
   return __sync_bool_compare_and_swap(ptr, old_value, new_value);
#else
#  error No implementation
#endif
}

这是使用便携式快速代码的最合适方式吗(除了程序集内联)。

另外,一个问题是那些特定的builtin方法具有不同的参数并且从一个编译器返回另一个编译器的值,这可能需要一些额外的更改,例如本例中的if then else

另一个问题是机器代码级别中这些builtin方法的行为,它们的行为是否完全相同? (例如使用相同的装配说明)

注意:另一个问题是,如果此示例中有许多受支持的平台(WindowsLinux)。代码可能会变得很大。

3 个答案:

答案 0 :(得分:3)

我会使用硬件抽象层(HAL),它允许通用代码通用 - 并且可以为每个平台包含和构建任何可移植源。

在我看来,这允许更好的结构化和更可读的来源。

为了让您更好地了解此过程,我建议Google查找示例和解释。

希望这个简短的回答有所帮助。

[编辑]我将尝试一个Bionix的简单示例,以展示如何实现HAL系统......

  • A先生希望他的申请能在他的“天河2号”上运行。以及他的Amiga 500'。他有交叉编译器等,并将在他的PC上构建两个二进制文件。他想读取键并打印到屏幕上。

mrAMainApplication.c包含以下内容......

#include "hal.h"

// This gets called every time around the main loop ...
void mainProcessLoop( void )
{
   unsigned char key = 0;

   // scan key ...
   key = hal_ReadKey();

   if ( key != 0 )
   {
       hal_PrintChar( key );
   }
}
然后他创建了一个头文件(记住 - 这是一个例子,不是工作代码!)......  他创造了hal.h ......

#ifndef _HAL_H_
#define _HAL_H_

unsigned char hal_ReadKey( void );
unsigned char hal_PrintChar( unsigned char pKey );

#endif // _HAL_H_

现在A先生需要两个单独的源文件,一个用于他的'天河-2'系统和另一个为他的Amiga 500 ...

hal_A500.c

void hal_ReadKey( void )
{
    // Amiga related code for reading KEYBOARD
}

void hal_PrintChar( unsigned char pKey )
{
    // Amiga related code for printing to a shell...
}

hal_Tianhe2_VERYFAST.c

void hal_ReadKey( void )
{
    // Tianhe-2 related code for reading KEYBOARD
}

void hal_PrintChar( unsigned char pKey )
{
    // Tianhe-2 related code for printing to a shell...
}

A先生 - 当为Amiga建设时 - 建立mrAmainApplication.c和hal_A500.c 为天河2号建造时 - 他使用hal_Tianhe2_VERYFAST.c而不是hal_A500.c

是的 - 我用一些幽默写了这个例子,这对任何人来说都没有标记,只是我觉得它让这个例子更有趣,并希望有助于理解。

尼尔

答案 1 :(得分:1)

看看ConcurrencyKit,可能你可以使用更高级别的原语,这可能是大多数人真正想要的。与某些操作系统特定的HAL相比,我认为CK适用于Windows以及许多非gcc编译器。

但是如果你只是对如何实施"比较和交换"感兴趣?或者在各种C编译器上可移植的原子操作,查看并查看该代码的工作原理。它都是开源的。

我怀疑细节可能会变得混乱,而且对于普通大众而言,这些细节通常不会为简单或有趣的阐述做出贡献。

答案 2 :(得分:1)

在现代C中,从C11开始,使用_Atomic作为类型限定,使用atomic_compare_exchange_weak作为函数。

新版本的gcc和clang符合C11标准,并以便携方式实现这些操作。