Swift中使用C11標準的原子操作

來源:互聯網
上載者:User

當前Swift 3.0中還沒有正式引入基本類型相對應的原子類型。而在macOS以及iOS下,我們可以用系統內建的OSAtomic API進行原子操作處理。但這組API只能在Apple自家平台上使用,我們無法在Linux/FreeBSD中使用,所以我這邊封裝了順應C11標準的一組原子類型與原子操作提供給Swift程式設計語言。


當前在Swift中,如果我們在C語言標頭檔聲明了一個比如atomic_int類型的全域對象,那麼該對象在Swift中是無法被匯入的,因為atomic_int類型在Swift中無法被轉換為它所能識別的相應類型。所以,我這邊的思路是將C11標準中支援的原子類型通過結構體進行封裝。我在下列代碼中封裝了3種原子類型,分別為:atomic_int、atomic_bool以及atomic_uint_fast64_t,分別表示int原子類型、布爾原子類型以及無符號64位整數原子類型。我這邊建立的項目名為SwiftTest,所以Swift所需要的橋接標頭檔名為SwiftTest-Bridging-Header.h。下面先給出此標頭檔的完整原始碼:

#include <stdint.h>#include <stdbool.h>#include <stdatomic.h>/** 用於Swift的AtomicInt原子類型 */struct AtomicIntSwift {    volatile atomic_int atom;};/** * 對原子物件進行初始化 * @param pAtom 指向Swift中AtomicInt類型的原子物件,並且不允許為空白 * @param value 指定要給原子物件初始化的值*/extern void __attribute__((overloadable)) AtomicSwiftInit(struct AtomicIntSwift* __nonnull pAtom, int value);/** * 對原子物件進行載入操作 * @param pAtom 指向Swift中AtomicInt類型的原子物件,並且不允許為空白 * @return 指定原子物件所儲存的值*/extern int __attribute__((overloadable)) AtomicSwiftLoad(struct AtomicIntSwift* __nonnull pAtom);/**  * 對原子物件進行儲存操作 * @param pAtom 指向Swift中AtomicInt類型的原子物件,並且不允許為空白 * @param value 要儲存到指定原子物件中的值*/extern void __attribute__((overloadable)) AtomicSwiftStore(struct AtomicIntSwift* __nonnull pAtom, int value);/** * 將原子物件中存放的值與所指定的基本類型的值進行交換。 * * 也就是說,將基本類型的值存放到原子物件中去,並將原子物件的原始值返回 * @param pAtom 指向Swift中AtomicInt類型的原子物件,並且不允許為空白 * @param value 指定的基本類型的值 * @return 原子物件的原始值*/extern int __attribute__((overloadable)) AtomicSwiftExchange(struct AtomicIntSwift* __nonnull pAtom, int value);/** * 原子比較與交換 * * 將原子物件中的值與expected的值進行比較,如果相同則將desired的值寫入到原子物件中,並返回true; * 否則,將當前原子物件中的值寫入到expected中去,並返回false * @param pAtom 指向Swift中AtomicInt類型的原子物件,並且不允許為空白 * @param expected 存放與原子物件進行比較的值的指標。 *                 該指標一般指向用原子載入操作所得到值的變數,並且不可為空。 * @param desired 要存入到原子物件中的值 * @return 如果expected中的值與原子物件中所存放的值相同,則返回true,否則返回false*/extern bool __attribute__((overloadable)) AtomicSwiftCAS(struct AtomicIntSwift* __nonnull pAtom, int* __nonnull expected, int desired);/** * 原子加法操作 * @param pAtom 指向Swift中AtomicInt類型的原子物件,並且不允許為空白 * @param value 指定的基本類型的值 * @return 原子物件的原始值*/extern int __attribute__((overloadable)) AtomicSwiftFetchAdd(struct AtomicIntSwift* __nonnull pAtom, int value);/** * 原子減法操作 * @param pAtom 指向Swift中AtomicInt類型的原子物件,並且不允許為空白 * @param value 指定的基本類型的值 * @return 原子物件的原始值*/extern int __attribute__((overloadable)) AtomicSwiftFetchSub(struct AtomicIntSwift* __nonnull pAtom, int value);/** * 原子按位或操作 * @param pAtom 指向Swift中AtomicInt類型的原子物件,並且不允許為空白 * @param value 指定的基本類型的值 * @return 原子物件的原始值*/extern int __attribute__((overloadable)) AtomicSwiftFetchOr(struct AtomicIntSwift* __nonnull pAtom, int value);/** * 原子按位異或操作 * @param pAtom 指向Swift中AtomicInt類型的原子物件,並且不允許為空白 * @param value 指定的基本類型的值 * @return 原子物件的原始值*/extern int __attribute__((overloadable)) AtomicSwiftFetchXor(struct AtomicIntSwift* __nonnull pAtom, int value);/** * 原子按位與操作 * @param pAtom 指向Swift中AtomicInt類型的原子物件,並且不允許為空白 * @param value 指定的基本類型的值 * @return 原子物件的原始值*/extern int __attribute__((overloadable)) AtomicSwiftFetchAnd(struct AtomicIntSwift* __nonnull pAtom, int value);/** 用於Swift的AtomicBool原子類型 */struct AtomicBoolSwift {    volatile atomic_bool atom;};/** * 對原子物件進行初始化 * @param pAtom 指向Swift中AtomicBool類型的原子物件,並且不允許為空白 * @param value 指定要給原子物件初始化的值*/extern void __attribute__((overloadable)) AtomicSwiftInit(struct AtomicBoolSwift* __nonnull pAtom, bool value);/** * 對原子物件進行載入操作 * @param pAtom 指向Swift中AtomicBool類型的原子物件,並且不允許為空白 * @return 指定原子物件所儲存的值*/extern bool __attribute__((overloadable)) AtomicSwiftLoad(struct AtomicBoolSwift* __nonnull pAtom);/** * 對原子物件進行儲存操作 * @param pAtom 指向Swift中AtomicBool類型的原子物件,並且不允許為空白 * @param value 要儲存到指定原子物件中的值 */extern void __attribute__((overloadable)) AtomicSwiftStore(struct AtomicBoolSwift* __nonnull pAtom, bool value);/** * 將原子物件中存放的值與所指定的基本類型的值進行交換。 * * 也就是說,將基本類型的值存放到原子物件中去,並將原子物件的原始值返回 * @param pAtom 指向Swift中AtomicBool類型的原子物件,並且不允許為空白 * @param value 指定的基本類型的值 * @return 原子物件的原始值*/extern bool __attribute__((overloadable)) AtomicSwiftExchange(struct AtomicBoolSwift* __nonnull pAtom, bool value);/** * 原子比較與交換 * * 將原子物件中的值與expected的值進行比較,如果相同則將desired的值寫入到原子物件中,並返回true; * 否則,將當前原子物件中的值寫入到expected中去,並返回false * @param pAtom 指向Swift中AtomicBool類型的原子物件,並且不允許為空白 * @param expected 存放與原子物件進行比較的值的指標。 *                 該指標一般指向用原子載入操作所得到值的變數,並且不可為空。 * @param desired 要存入到原子物件中的值 * @return 如果expected中的值與原子物件中所存放的值相同,則返回true,否則返回false*/extern bool __attribute__((overloadable)) AtomicSwiftCAS(struct AtomicBoolSwift* __nonnull pAtom, bool* __nonnull expected, bool desired);/** 用於Swift的AtomicULong原子類型 */struct AtomicULongSwift {    volatile atomic_uint_fast64_t atom;};/** * 對原子物件進行初始化 * @param pAtom 指向Swift中AtomicULong類型的原子物件,並且不允許為空白 * @param value 指定要給原子物件初始化的值*/extern void __attribute__((overloadable)) AtomicSwiftInit(struct AtomicULongSwift* __nonnull pAtom, uint64_t value);/** * 對原子物件進行載入操作 * @param pAtom 指向Swift中AtomicULong類型的原子物件,並且不允許為空白 * @return 指定原子物件所儲存的值*/extern uint64_t __attribute__((overloadable)) AtomicSwiftLoad(struct AtomicULongSwift* __nonnull pAtom);/** * 對原子物件進行儲存操作 * @param pAtom 指向Swift中AtomicULong類型的原子物件,並且不允許為空白 * @param value 要儲存到指定原子物件中的值*/extern void __attribute__((overloadable)) AtomicSwiftStore(struct AtomicULongSwift* __nonnull pAtom, uint64_t value);/** * 將原子物件中存放的值與所指定的基本類型的值進行交換。 * * 也就是說,將基本類型的值存放到原子物件中去,並將原子物件的原始值返回 * @param pAtom 指向Swift中AtomicULong類型的原子物件,並且不允許為空白 * @param value 指定的基本類型的值 * @return 原子物件的原始值*/extern uint64_t __attribute__((overloadable)) AtomicSwiftExchange(struct AtomicULongSwift* __nonnull pAtom, uint64_t value);/** * 原子比較與交換 * * 將原子物件中的值與expected的值進行比較,如果相同則將desired的值寫入到原子物件中,並返回true; * 否則,將當前原子物件中的值寫入到expected中去,並返回false * @param pAtom 指向Swift中AtomicULong類型的原子物件,並且不允許為空白 * @param expected 存放與原子物件進行比較的值的指標。 *                 該指標一般指向用原子載入操作所得到值的變數,並且不可為空。 * @param desired 要存入到原子物件中的值 * @return 如果expected中的值與原子物件中所存放的值相同,則返回true,否則返回false*/extern bool __attribute__((overloadable)) AtomicSwiftCAS(struct AtomicULongSwift* __nonnull pAtom, uint64_t* __nonnull expected, uint64_t desired);/** * 原子加法操作 * @param pAtom 指向Swift中AtomicULong類型的原子物件,並且不允許為空白 * @param value 指定的基本類型的值 * @return 原子物件的原始值*/extern uint64_t __attribute__((overloadable)) AtomicSwiftFetchAdd(struct AtomicULongSwift* __nonnull pAtom, uint64_t value);/** * 原子減法操作 * @param pAtom 指向Swift中AtomicULong類型的原子物件,並且不允許為空白 * @param value 指定的基本類型的值 * @return 原子物件的原始值*/extern uint64_t __attribute__((overloadable)) AtomicSwiftFetchSub(struct AtomicULongSwift* __nonnull pAtom, uint64_t value);/** * 原子按位或操作 * @param pAtom 指向Swift中AtomicULong類型的原子物件,並且不允許為空白 * @param value 指定的基本類型的值 * @return 原子物件的原始值*/extern uint64_t __attribute__((overloadable)) AtomicSwiftFetchOr(struct AtomicULongSwift* __nonnull pAtom, uint64_t value);/** * 原子按位異或操作 * @param pAtom 指向Swift中AtomicULong類型的原子物件,並且不允許為空白 * @param value 指定的基本類型的值 * @return 原子物件的原始值*/extern uint64_t __attribute__((overloadable)) AtomicSwiftFetchXor(struct AtomicULongSwift* __nonnull pAtom, uint64_t value);/** * 原子按位與操作 * @param pAtom 指向Swift中AtomicULong類型的原子物件,並且不允許為空白 * @param value 指定的基本類型的值 * @return 原子物件的原始值*/extern uint64_t __attribute__((overloadable)) AtomicSwiftFetchAnd(struct AtomicULongSwift* __nonnull pAtom, uint64_t value);

上述代碼列出了我們後面在Swift中所需要的C語言底層對C11標準原子操作的封裝實現。下面我們可以在C源檔案(.c檔案)中實現這些聲明的函數介面。

#include <stdio.h>#include "SwiftTest-Bridging-Header.h"#pragma mark - atomic intvoid __attribute__((overloadable)) AtomicSwiftInit(struct AtomicIntSwift* __nonnull pAtom, int value){    if(pAtom == NULL)        return;        atomic_init(&pAtom->atom, value);}int __attribute__((overloadable)) AtomicSwiftLoad(struct AtomicIntSwift* __nonnull pAtom){    if(pAtom == NULL)        return 0;        return atomic_load(&pAtom->atom);}void __attribute__((overloadable)) AtomicSwiftStore(struct AtomicIntSwift* __nonnull pAtom, int value){    if(pAtom == NULL)        return;        atomic_store(&pAtom->atom, value);}int __attribute__((overloadable)) AtomicSwiftExchange(struct AtomicIntSwift* __nonnull pAtom, int value){    if(pAtom == NULL)        return 0;        return atomic_exchange(&pAtom->atom, value);}bool __attribute__((overloadable)) AtomicSwiftCAS(struct AtomicIntSwift* __nonnull pAtom, int* __nonnull expected, int desired){    if(pAtom == NULL || expected == NULL)        return false;        return atomic_compare_exchange_weak(&pAtom->atom, expected, desired);}int __attribute__((overloadable)) AtomicSwiftFetchAdd(struct AtomicIntSwift* __nonnull pAtom, int value){    if(pAtom == NULL)        return 0;        return atomic_fetch_add(&pAtom->atom, value);}int __attribute__((overloadable)) AtomicSwiftFetchSub(struct AtomicIntSwift* __nonnull pAtom, int value){    if(pAtom == NULL)        return 0;        return atomic_fetch_sub(&pAtom->atom, value);}int __attribute__((overloadable)) AtomicSwiftFetchOr(struct AtomicIntSwift* __nonnull pAtom, int value){    if(pAtom == NULL)        return 0;        return atomic_fetch_or(&pAtom->atom, value);}int __attribute__((overloadable)) AtomicSwiftFetchXor(struct AtomicIntSwift* __nonnull pAtom, int value){    if(pAtom == NULL)        return 0;        return atomic_fetch_xor(&pAtom->atom, value);}int __attribute__((overloadable)) AtomicSwiftFetchAnd(struct AtomicIntSwift* __nonnull pAtom, int value){    if(pAtom == NULL)        return 0;        return atomic_fetch_and(&pAtom->atom, value);}#pragma mark - atomic boolvoid __attribute__((overloadable)) AtomicSwiftInit(struct AtomicBoolSwift* __nonnull pAtom, bool value){    if(pAtom == NULL)        return;        atomic_init(&pAtom->atom, value);}bool __attribute__((overloadable)) AtomicSwiftLoad(struct AtomicBoolSwift* __nonnull pAtom){    if(pAtom == NULL)        return false;        return atomic_load(&pAtom->atom);}void __attribute__((overloadable)) AtomicSwiftStore(struct AtomicBoolSwift* __nonnull pAtom, bool value){    if(pAtom == NULL)        return;        atomic_store(&pAtom->atom, value);}bool __attribute__((overloadable)) AtomicSwiftExchange(struct AtomicBoolSwift* __nonnull pAtom, bool value){    if(pAtom == NULL)        return false;        return atomic_exchange(&pAtom->atom, value);}bool __attribute__((overloadable)) AtomicSwiftCAS(struct AtomicBoolSwift* __nonnull pAtom, bool* __nonnull expected, bool desired){    if(pAtom == NULL || expected == NULL)        return false;        return atomic_compare_exchange_weak(&pAtom->atom, expected, desired);}#pragma mark - atomic uint64_tvoid __attribute__((overloadable)) AtomicSwiftInit(struct AtomicULongSwift* __nonnull pAtom, uint64_t value){    if(pAtom == NULL)        return;        atomic_init(&pAtom->atom, value);}uint64_t __attribute__((overloadable)) AtomicSwiftLoad(struct AtomicULongSwift* __nonnull pAtom){    if(pAtom == NULL)        return 0;        return atomic_load(&pAtom->atom);}void __attribute__((overloadable)) AtomicSwiftStore(struct AtomicULongSwift* __nonnull pAtom, uint64_t value){    if(pAtom == NULL)        return;        atomic_store(&pAtom->atom, value);}uint64_t __attribute__((overloadable)) AtomicSwiftExchange(struct AtomicULongSwift* __nonnull pAtom, uint64_t value){    if(pAtom == NULL)        return 0;        return atomic_exchange(&pAtom->atom, value);}bool __attribute__((overloadable)) AtomicSwiftCAS(struct AtomicULongSwift* __nonnull pAtom, uint64_t* __nonnull expected, uint64_t desired){    if(pAtom == NULL || expected == NULL)        return false;        return atomic_compare_exchange_weak(&pAtom->atom, expected, desired);}uint64_t __attribute__((overloadable)) AtomicSwiftFetchAdd(struct AtomicULongSwift* __nonnull pAtom, uint64_t value){    if(pAtom == NULL)        return 0;        return atomic_fetch_add(&pAtom->atom, value);}uint64_t __attribute__((overloadable)) AtomicSwiftFetchSub(struct AtomicULongSwift* __nonnull pAtom, uint64_t value){    if(pAtom == NULL)        return 0;        return atomic_fetch_sub(&pAtom->atom, value);}uint64_t __attribute__((overloadable)) AtomicSwiftFetchOr(struct AtomicULongSwift* __nonnull pAtom, uint64_t value){    if(pAtom == NULL)        return 0;        return atomic_fetch_or(&pAtom->atom, value);}uint64_t __attribute__((overloadable)) AtomicSwiftFetchXor(struct AtomicULongSwift* __nonnull pAtom, uint64_t value){    if(pAtom == NULL)        return 0;        return atomic_fetch_xor(&pAtom->atom, value);}uint64_t __attribute__((overloadable)) AtomicSwiftFetchAnd(struct AtomicULongSwift* __nonnull pAtom, uint64_t value){    if(pAtom == NULL)        return 0;        return atomic_fetch_and(&pAtom->atom, value);}

我們看到,這個封裝實現其實不是很複雜。為了能讓原子操作在Swift中更OO化,我在Swift中將每個原子類型抽象為一個結構體。下面我們來看Swift源檔案:

/** 所有原子類型所需遵循的原子類型協議 */

public protocol AtomicType {

    

    /** 當前原子類型所對應的基本類型 */

    associatedtype RawType

    

    /** 初始化器,對當前原子物件初始化為0值。它不具有原子性 */

    init()

    

    /**

     初始化器,對當前原子物件初始化為形參指定的值。它不具有原子性

     

     - parameters:

        - value: 為當前原子物件初始化的初始值

    */

    init(value: RawType)

    

    /**

     載入當前原子物件的值,並返回。

     

     - returns:當前原子物件對應的基本類型的值

    */

    mutatingfunc load() -> RawType

    

    /**

     將一個指定的基本類型值存放到當前原子物件中

     

     - parameters:

        - value: 指定要存放的基本類型的值

    */

    mutatingfunc store(by value: RawType)

    

    /**

     將指定的基本類型的值存入當前原子物件中,並返回存入之前的原子物件的原始值

     

     - parameters:

        - value: 指定的基本類型的值

     

     - returns:在將指定值存入之前的原子物件的原始值

    */

    mutatingfunc exchange(with value: RawType) -> RawType

    

    /**

     原子比較與交換。

     

     

     當前原子物件的值先與expected的值進行比較,如果相同則將desired的值存入當前原子物件,並返回true;

     否則將當前原子物件的值存入expected,然後返回false。

     

     - parameters:

        - expected: 指向基本類型對象的指標。

                    此基本類型對象在調用該函數前一般會用load方法將當前原子物件的值載入進去。

        - desired: 最終所要寫入的值

     

     - returns:如果當前原子物件的值與expected中的值相同,那麼返回true,否則返回false

    */

    mutatingfunc cas(expected: UnsafeMutablePointer<RawType>, desired: RawType) ->Bool

    

    /**

     原子加法操作

     

     - parameters:

        - operand: 加法運算元

     

     - returns:加法操作之前原子物件的原始值

    */

    mutatingfunc fetch_add(operand: RawType) -> RawType

    

    /**

     原子減法操作

     

     - parameters:

        - operand: 減法運算元

     

     - returns:減法操作之前原子物件的原始值

    */

    mutatingfunc fetch_sub(operand: RawType) -> RawType

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.