當前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