如何实现便携式指针比较和交换?
How can I implement a portable pointer compare and swap?
我在 a Whosebug 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
方法从一个编译器到另一个编译器具有不同的参数和 return 值,这可能需要一些额外的更改,例如此中的 if then else
例子。
另一个问题是这些 builtin
方法在机器代码级别的行为,它们的行为是否完全相同? (例如使用相同的汇编指令)
注意: 另一个问题是,如果有许多受支持的平台,而不仅仅是本示例中的(Windows
和 Linux
)。代码可能会变得非常大。
我会使用 硬件抽象层 ,(HAL),它允许通用代码通用 - 并且可以包含任何可移植源并为每个平台构建。
在我看来,这允许更好的结构化和更具可读性的来源。
为了让您更好地理解这个过程,我建议 Google 查找示例和解释。
希望这个简短的回答对您有所帮助。
[编辑] 我将尝试为 Bionix 做一个简单的例子,展示如何实现 HAL 系统...
- A 先生希望在 'Tianhe-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 先生需要两个单独的源文件,一个用于他的 'Tianhe-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
在建造天河二号时 - 他使用 hal_Tianhe2_VERYFAST.c 而不是 hal_A500.c
是的 - 我写这个例子有点幽默,这不是任何人的耳标,只是我觉得它使这个例子更有趣,希望有助于理解。
尼尔
看看 ConcurrencyKit,您可能可以使用更高级别的原语,这可能是大多数时候人们真正想要的。与有点 OS 具体的 HAL 相比,我相信 CK 适用于 Windows 和许多非 gcc 编译器。
但是,如果您只是对如何在各种 C 编译器上可移植地实现 "compare-and-swap" 或原子操作感兴趣,请查看该代码的工作原理。这都是开源的。
我怀疑细节可能会变得混乱,并且通常不会在这里为一般性 public 进行简单或有趣的阐述。
在现代 C 中,从 C11 开始,使用 _Atomic
作为类型限定,使用 atomic_compare_exchange_weak
作为函数。
较新版本的 gcc 和 clang 与 C11 兼容,并以可移植的方式实现这些操作。
我在 a Whosebug 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
方法从一个编译器到另一个编译器具有不同的参数和 return 值,这可能需要一些额外的更改,例如此中的 if then else
例子。
另一个问题是这些 builtin
方法在机器代码级别的行为,它们的行为是否完全相同? (例如使用相同的汇编指令)
注意: 另一个问题是,如果有许多受支持的平台,而不仅仅是本示例中的(Windows
和 Linux
)。代码可能会变得非常大。
我会使用 硬件抽象层 ,(HAL),它允许通用代码通用 - 并且可以包含任何可移植源并为每个平台构建。
在我看来,这允许更好的结构化和更具可读性的来源。
为了让您更好地理解这个过程,我建议 Google 查找示例和解释。
希望这个简短的回答对您有所帮助。
[编辑] 我将尝试为 Bionix 做一个简单的例子,展示如何实现 HAL 系统...
- A 先生希望在 'Tianhe-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 先生需要两个单独的源文件,一个用于他的 'Tianhe-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 在建造天河二号时 - 他使用 hal_Tianhe2_VERYFAST.c 而不是 hal_A500.c
是的 - 我写这个例子有点幽默,这不是任何人的耳标,只是我觉得它使这个例子更有趣,希望有助于理解。
尼尔
看看 ConcurrencyKit,您可能可以使用更高级别的原语,这可能是大多数时候人们真正想要的。与有点 OS 具体的 HAL 相比,我相信 CK 适用于 Windows 和许多非 gcc 编译器。
但是,如果您只是对如何在各种 C 编译器上可移植地实现 "compare-and-swap" 或原子操作感兴趣,请查看该代码的工作原理。这都是开源的。
我怀疑细节可能会变得混乱,并且通常不会在这里为一般性 public 进行简单或有趣的阐述。
在现代 C 中,从 C11 开始,使用 _Atomic
作为类型限定,使用 atomic_compare_exchange_weak
作为函数。
较新版本的 gcc 和 clang 与 C11 兼容,并以可移植的方式实现这些操作。