Fast atomics (#1263)
Motivation: The existing Atomic class holds an UnsafeEmbeddedAtomic which holds an OpaquePointer to raw memory for the C atomic. This results in multiple allocations on init. The new NIOAtomic class uses ManagedBufferPointer which tail allocates memory for the C atomic as part of the NIOAtomic class allocation. Modifications: Created NIOAtomic class that uses ManagedBufferPointer to allocate memory for the C atomic. Created version of catmc_atomic_* C functions that expect memory to be allocated/deallocated by caller. Created NIOAtomicPrimitive protocol for the new version of catmc_atomic_* functions. Result: Purely additive. NIOAtomic is available as a replacement for Atomic which results in fewer memory allocations.
This commit is contained in:
parent
abe5219b71
commit
3c879ebbaf
|
@ -2,7 +2,7 @@
|
|||
//
|
||||
// This source file is part of the SwiftNIO open source project
|
||||
//
|
||||
// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors
|
||||
// Copyright (c) 2017-2019 Apple Inc. and the SwiftNIO project authors
|
||||
// Licensed under Apache License v2.0
|
||||
//
|
||||
// See LICENSE.txt for license information
|
||||
|
@ -231,3 +231,267 @@ uint_least64_t catmc_atomic_uint_least64_t_sub(struct catmc_atomic_uint_least64_
|
|||
uint_least64_t catmc_atomic_uint_least64_t_exchange(struct catmc_atomic_uint_least64_t * _Nonnull atomic, uint_least64_t value);
|
||||
uint_least64_t catmc_atomic_uint_least64_t_load(struct catmc_atomic_uint_least64_t * _Nonnull atomic);
|
||||
void catmc_atomic_uint_least64_t_store(struct catmc_atomic_uint_least64_t * _Nonnull atomic, uint_least64_t value);
|
||||
|
||||
struct catmc_nio_atomic__Bool {
|
||||
_Atomic _Bool value;
|
||||
};
|
||||
void catmc_nio_atomic__Bool_create_with_existing_storage(struct catmc_nio_atomic__Bool * _Nonnull storage, bool value);
|
||||
bool catmc_nio_atomic__Bool_compare_and_exchange(struct catmc_nio_atomic__Bool * _Nonnull atomic, bool expected, bool desired);
|
||||
bool catmc_nio_atomic__Bool_add(struct catmc_nio_atomic__Bool * _Nonnull atomic, bool value);
|
||||
bool catmc_nio_atomic__Bool_sub(struct catmc_nio_atomic__Bool * _Nonnull atomic, bool value);
|
||||
bool catmc_nio_atomic__Bool_exchange(struct catmc_nio_atomic__Bool * _Nonnull atomic, bool value);
|
||||
bool catmc_nio_atomic__Bool_load(struct catmc_nio_atomic__Bool * _Nonnull atomic);
|
||||
void catmc_nio_atomic__Bool_store(struct catmc_nio_atomic__Bool * _Nonnull atomic, bool value);
|
||||
|
||||
struct catmc_nio_atomic_char {
|
||||
_Atomic char value;
|
||||
};
|
||||
void catmc_nio_atomic_char_create_with_existing_storage(struct catmc_nio_atomic_char * _Nonnull storage, char value);
|
||||
bool catmc_nio_atomic_char_compare_and_exchange(struct catmc_nio_atomic_char * _Nonnull atomic, char expected, char desired);
|
||||
char catmc_nio_atomic_char_add(struct catmc_nio_atomic_char * _Nonnull atomic, char value);
|
||||
char catmc_nio_atomic_char_sub(struct catmc_nio_atomic_char * _Nonnull atomic, char value);
|
||||
char catmc_nio_atomic_char_exchange(struct catmc_nio_atomic_char * _Nonnull atomic, char value);
|
||||
char catmc_nio_atomic_char_load(struct catmc_nio_atomic_char * _Nonnull atomic);
|
||||
void catmc_nio_atomic_char_store(struct catmc_nio_atomic_char * _Nonnull atomic, char value);
|
||||
|
||||
struct catmc_nio_atomic_short {
|
||||
_Atomic short value;
|
||||
};
|
||||
void catmc_nio_atomic_short_create_with_existing_storage(struct catmc_nio_atomic_short * _Nonnull storage, short value);
|
||||
bool catmc_nio_atomic_short_compare_and_exchange(struct catmc_nio_atomic_short * _Nonnull atomic, short expected, short desired);
|
||||
short catmc_nio_atomic_short_add(struct catmc_nio_atomic_short * _Nonnull atomic, short value);
|
||||
short catmc_nio_atomic_short_sub(struct catmc_nio_atomic_short * _Nonnull atomic, short value);
|
||||
short catmc_nio_atomic_short_exchange(struct catmc_nio_atomic_short * _Nonnull atomic, short value);
|
||||
short catmc_nio_atomic_short_load(struct catmc_nio_atomic_short * _Nonnull atomic);
|
||||
void catmc_nio_atomic_short_store(struct catmc_nio_atomic_short * _Nonnull atomic, short value);
|
||||
|
||||
struct catmc_nio_atomic_int {
|
||||
_Atomic int value;
|
||||
};
|
||||
void catmc_nio_atomic_int_create_with_existing_storage(struct catmc_nio_atomic_int * _Nonnull storage, int value);
|
||||
bool catmc_nio_atomic_int_compare_and_exchange(struct catmc_nio_atomic_int * _Nonnull atomic, int expected, int desired);
|
||||
int catmc_nio_atomic_int_add(struct catmc_nio_atomic_int * _Nonnull atomic, int value);
|
||||
int catmc_nio_atomic_int_sub(struct catmc_nio_atomic_int * _Nonnull atomic, int value);
|
||||
int catmc_nio_atomic_int_exchange(struct catmc_nio_atomic_int * _Nonnull atomic, int value);
|
||||
int catmc_nio_atomic_int_load(struct catmc_nio_atomic_int * _Nonnull atomic);
|
||||
void catmc_nio_atomic_int_store(struct catmc_nio_atomic_int * _Nonnull atomic, int value);
|
||||
|
||||
struct catmc_nio_atomic_long {
|
||||
_Atomic long value;
|
||||
};
|
||||
void catmc_nio_atomic_long_create_with_existing_storage(struct catmc_nio_atomic_long * _Nonnull storage, long value);
|
||||
bool catmc_nio_atomic_long_compare_and_exchange(struct catmc_nio_atomic_long * _Nonnull atomic, long expected, long desired);
|
||||
long catmc_nio_atomic_long_add(struct catmc_nio_atomic_long * _Nonnull atomic, long value);
|
||||
long catmc_nio_atomic_long_sub(struct catmc_nio_atomic_long * _Nonnull atomic, long value);
|
||||
long catmc_nio_atomic_long_exchange(struct catmc_nio_atomic_long * _Nonnull atomic, long value);
|
||||
long catmc_nio_atomic_long_load(struct catmc_nio_atomic_long * _Nonnull atomic);
|
||||
void catmc_nio_atomic_long_store(struct catmc_nio_atomic_long * _Nonnull atomic, long value);
|
||||
|
||||
struct catmc_nio_atomic_long_long {
|
||||
_Atomic long long value;
|
||||
};
|
||||
void catmc_nio_atomic_long_long_create_with_existing_storage(struct catmc_nio_atomic_long_long * _Nonnull storage, long long value);
|
||||
bool catmc_nio_atomic_long_long_compare_and_exchange(struct catmc_nio_atomic_long_long * _Nonnull atomic, long long expected, long long desired);
|
||||
long long catmc_nio_atomic_long_long_add(struct catmc_nio_atomic_long_long * _Nonnull atomic, long long value);
|
||||
long long catmc_nio_atomic_long_long_sub(struct catmc_nio_atomic_long_long * _Nonnull atomic, long long value);
|
||||
long long catmc_nio_atomic_long_long_exchange(struct catmc_nio_atomic_long_long * _Nonnull atomic, long long value);
|
||||
long long catmc_nio_atomic_long_long_load(struct catmc_nio_atomic_long_long * _Nonnull atomic);
|
||||
void catmc_nio_atomic_long_long_store(struct catmc_nio_atomic_long_long * _Nonnull atomic, long long value);
|
||||
|
||||
struct catmc_nio_atomic_signed_char {
|
||||
_Atomic signed char value;
|
||||
};
|
||||
void catmc_nio_atomic_signed_char_create_with_existing_storage(struct catmc_nio_atomic_signed_char * _Nonnull storage, signed char value);
|
||||
bool catmc_nio_atomic_signed_char_compare_and_exchange(struct catmc_nio_atomic_signed_char * _Nonnull atomic, signed char expected, signed char desired);
|
||||
signed char catmc_nio_atomic_signed_char_add(struct catmc_nio_atomic_signed_char * _Nonnull atomic, signed char value);
|
||||
signed char catmc_nio_atomic_signed_char_sub(struct catmc_nio_atomic_signed_char * _Nonnull atomic, signed char value);
|
||||
signed char catmc_nio_atomic_signed_char_exchange(struct catmc_nio_atomic_signed_char * _Nonnull atomic, signed char value);
|
||||
signed char catmc_nio_atomic_signed_char_load(struct catmc_nio_atomic_signed_char * _Nonnull atomic);
|
||||
void catmc_nio_atomic_signed_char_store(struct catmc_nio_atomic_signed_char * _Nonnull atomic, signed char value);
|
||||
|
||||
struct catmc_nio_atomic_signed_short {
|
||||
_Atomic signed short value;
|
||||
};
|
||||
void catmc_nio_atomic_signed_short_create_with_existing_storage(struct catmc_nio_atomic_signed_short * _Nonnull storage, signed short value);
|
||||
bool catmc_nio_atomic_signed_short_compare_and_exchange(struct catmc_nio_atomic_signed_short * _Nonnull atomic, signed short expected, signed short desired);
|
||||
signed short catmc_nio_atomic_signed_short_add(struct catmc_nio_atomic_signed_short * _Nonnull atomic, signed short value);
|
||||
signed short catmc_nio_atomic_signed_short_sub(struct catmc_nio_atomic_signed_short * _Nonnull atomic, signed short value);
|
||||
signed short catmc_nio_atomic_signed_short_exchange(struct catmc_nio_atomic_signed_short * _Nonnull atomic, signed short value);
|
||||
signed short catmc_nio_atomic_signed_short_load(struct catmc_nio_atomic_signed_short * _Nonnull atomic);
|
||||
void catmc_nio_atomic_signed_short_store(struct catmc_nio_atomic_signed_short * _Nonnull atomic, signed short value);
|
||||
|
||||
struct catmc_nio_atomic_signed_int {
|
||||
_Atomic signed int value;
|
||||
};
|
||||
void catmc_nio_atomic_signed_int_create_with_existing_storage(struct catmc_nio_atomic_signed_int * _Nonnull storage, signed int value);
|
||||
bool catmc_nio_atomic_signed_int_compare_and_exchange(struct catmc_nio_atomic_signed_int * _Nonnull atomic, signed int expected, signed int desired);
|
||||
signed int catmc_nio_atomic_signed_int_add(struct catmc_nio_atomic_signed_int * _Nonnull atomic, signed int value);
|
||||
signed int catmc_nio_atomic_signed_int_sub(struct catmc_nio_atomic_signed_int * _Nonnull atomic, signed int value);
|
||||
signed int catmc_nio_atomic_signed_int_exchange(struct catmc_nio_atomic_signed_int * _Nonnull atomic, signed int value);
|
||||
signed int catmc_nio_atomic_signed_int_load(struct catmc_nio_atomic_signed_int * _Nonnull atomic);
|
||||
void catmc_nio_atomic_signed_int_store(struct catmc_nio_atomic_signed_int * _Nonnull atomic, signed int value);
|
||||
|
||||
struct catmc_nio_atomic_signed_long {
|
||||
_Atomic signed long value;
|
||||
};
|
||||
void catmc_nio_atomic_signed_long_create_with_existing_storage(struct catmc_nio_atomic_signed_long * _Nonnull storage, signed long value);
|
||||
bool catmc_nio_atomic_signed_long_compare_and_exchange(struct catmc_nio_atomic_signed_long * _Nonnull atomic, signed long expected, signed long desired);
|
||||
signed long catmc_nio_atomic_signed_long_add(struct catmc_nio_atomic_signed_long * _Nonnull atomic, signed long value);
|
||||
signed long catmc_nio_atomic_signed_long_sub(struct catmc_nio_atomic_signed_long * _Nonnull atomic, signed long value);
|
||||
signed long catmc_nio_atomic_signed_long_exchange(struct catmc_nio_atomic_signed_long * _Nonnull atomic, signed long value);
|
||||
signed long catmc_nio_atomic_signed_long_load(struct catmc_nio_atomic_signed_long * _Nonnull atomic);
|
||||
void catmc_nio_atomic_signed_long_store(struct catmc_nio_atomic_signed_long * _Nonnull atomic, signed long value);
|
||||
|
||||
struct catmc_nio_atomic_signed_long_long {
|
||||
_Atomic signed long long value;
|
||||
};
|
||||
void catmc_nio_atomic_signed_long_long_create_with_existing_storage(struct catmc_nio_atomic_signed_long_long * _Nonnull storage, signed long long value);
|
||||
bool catmc_nio_atomic_signed_long_long_compare_and_exchange(struct catmc_nio_atomic_signed_long_long * _Nonnull atomic, signed long long expected, signed long long desired);
|
||||
signed long long catmc_nio_atomic_signed_long_long_add(struct catmc_nio_atomic_signed_long_long * _Nonnull atomic, signed long long value);
|
||||
signed long long catmc_nio_atomic_signed_long_long_sub(struct catmc_nio_atomic_signed_long_long * _Nonnull atomic, signed long long value);
|
||||
signed long long catmc_nio_atomic_signed_long_long_exchange(struct catmc_nio_atomic_signed_long_long * _Nonnull atomic, signed long long value);
|
||||
signed long long catmc_nio_atomic_signed_long_long_load(struct catmc_nio_atomic_signed_long_long * _Nonnull atomic);
|
||||
void catmc_nio_atomic_signed_long_long_store(struct catmc_nio_atomic_signed_long_long * _Nonnull atomic, signed long long value);
|
||||
|
||||
struct catmc_nio_atomic_unsigned_char {
|
||||
_Atomic unsigned char value;
|
||||
};
|
||||
void catmc_nio_atomic_unsigned_char_create_with_existing_storage(struct catmc_nio_atomic_unsigned_char * _Nonnull storage, unsigned char value);
|
||||
bool catmc_nio_atomic_unsigned_char_compare_and_exchange(struct catmc_nio_atomic_unsigned_char * _Nonnull atomic, unsigned char expected, unsigned char desired);
|
||||
unsigned char catmc_nio_atomic_unsigned_char_add(struct catmc_nio_atomic_unsigned_char * _Nonnull atomic, unsigned char value);
|
||||
unsigned char catmc_nio_atomic_unsigned_char_sub(struct catmc_nio_atomic_unsigned_char * _Nonnull atomic, unsigned char value);
|
||||
unsigned char catmc_nio_atomic_unsigned_char_exchange(struct catmc_nio_atomic_unsigned_char * _Nonnull atomic, unsigned char value);
|
||||
unsigned char catmc_nio_atomic_unsigned_char_load(struct catmc_nio_atomic_unsigned_char * _Nonnull atomic);
|
||||
void catmc_nio_atomic_unsigned_char_store(struct catmc_nio_atomic_unsigned_char * _Nonnull atomic, unsigned char value);
|
||||
|
||||
struct catmc_nio_atomic_unsigned_short {
|
||||
_Atomic unsigned short value;
|
||||
};
|
||||
void catmc_nio_atomic_unsigned_short_create_with_existing_storage(struct catmc_nio_atomic_unsigned_short * _Nonnull storage, unsigned short value);
|
||||
bool catmc_nio_atomic_unsigned_short_compare_and_exchange(struct catmc_nio_atomic_unsigned_short * _Nonnull atomic, unsigned short expected, unsigned short desired);
|
||||
unsigned short catmc_nio_atomic_unsigned_short_add(struct catmc_nio_atomic_unsigned_short * _Nonnull atomic, unsigned short value);
|
||||
unsigned short catmc_nio_atomic_unsigned_short_sub(struct catmc_nio_atomic_unsigned_short * _Nonnull atomic, unsigned short value);
|
||||
unsigned short catmc_nio_atomic_unsigned_short_exchange(struct catmc_nio_atomic_unsigned_short * _Nonnull atomic, unsigned short value);
|
||||
unsigned short catmc_nio_atomic_unsigned_short_load(struct catmc_nio_atomic_unsigned_short * _Nonnull atomic);
|
||||
void catmc_nio_atomic_unsigned_short_store(struct catmc_nio_atomic_unsigned_short * _Nonnull atomic, unsigned short value);
|
||||
|
||||
struct catmc_nio_atomic_unsigned_int {
|
||||
_Atomic unsigned int value;
|
||||
};
|
||||
void catmc_nio_atomic_unsigned_int_create_with_existing_storage(struct catmc_nio_atomic_unsigned_int * _Nonnull storage, unsigned int value);
|
||||
bool catmc_nio_atomic_unsigned_int_compare_and_exchange(struct catmc_nio_atomic_unsigned_int * _Nonnull atomic, unsigned int expected, unsigned int desired);
|
||||
unsigned int catmc_nio_atomic_unsigned_int_add(struct catmc_nio_atomic_unsigned_int * _Nonnull atomic, unsigned int value);
|
||||
unsigned int catmc_nio_atomic_unsigned_int_sub(struct catmc_nio_atomic_unsigned_int * _Nonnull atomic, unsigned int value);
|
||||
unsigned int catmc_nio_atomic_unsigned_int_exchange(struct catmc_nio_atomic_unsigned_int * _Nonnull atomic, unsigned int value);
|
||||
unsigned int catmc_nio_atomic_unsigned_int_load(struct catmc_nio_atomic_unsigned_int * _Nonnull atomic);
|
||||
void catmc_nio_atomic_unsigned_int_store(struct catmc_nio_atomic_unsigned_int * _Nonnull atomic, unsigned int value);
|
||||
|
||||
struct catmc_nio_atomic_unsigned_long {
|
||||
_Atomic unsigned long value;
|
||||
};
|
||||
void catmc_nio_atomic_unsigned_long_create_with_existing_storage(struct catmc_nio_atomic_unsigned_long * _Nonnull storage, unsigned long value);
|
||||
bool catmc_nio_atomic_unsigned_long_compare_and_exchange(struct catmc_nio_atomic_unsigned_long * _Nonnull atomic, unsigned long expected, unsigned long desired);
|
||||
unsigned long catmc_nio_atomic_unsigned_long_add(struct catmc_nio_atomic_unsigned_long * _Nonnull atomic, unsigned long value);
|
||||
unsigned long catmc_nio_atomic_unsigned_long_sub(struct catmc_nio_atomic_unsigned_long * _Nonnull atomic, unsigned long value);
|
||||
unsigned long catmc_nio_atomic_unsigned_long_exchange(struct catmc_nio_atomic_unsigned_long * _Nonnull atomic, unsigned long value);
|
||||
unsigned long catmc_nio_atomic_unsigned_long_load(struct catmc_nio_atomic_unsigned_long * _Nonnull atomic);
|
||||
void catmc_nio_atomic_unsigned_long_store(struct catmc_nio_atomic_unsigned_long * _Nonnull atomic, unsigned long value);
|
||||
|
||||
struct catmc_nio_atomic_unsigned_long_long {
|
||||
_Atomic unsigned long long value;
|
||||
};
|
||||
void catmc_nio_atomic_unsigned_long_long_create_with_existing_storage(struct catmc_nio_atomic_unsigned_long_long * _Nonnull storage, unsigned long long value);
|
||||
bool catmc_nio_atomic_unsigned_long_long_compare_and_exchange(struct catmc_nio_atomic_unsigned_long_long * _Nonnull atomic, unsigned long long expected, unsigned long long desired);
|
||||
unsigned long long catmc_nio_atomic_unsigned_long_long_add(struct catmc_nio_atomic_unsigned_long_long * _Nonnull atomic, unsigned long long value);
|
||||
unsigned long long catmc_nio_atomic_unsigned_long_long_sub(struct catmc_nio_atomic_unsigned_long_long * _Nonnull atomic, unsigned long long value);
|
||||
unsigned long long catmc_nio_atomic_unsigned_long_long_exchange(struct catmc_nio_atomic_unsigned_long_long * _Nonnull atomic, unsigned long long value);
|
||||
unsigned long long catmc_nio_atomic_unsigned_long_long_load(struct catmc_nio_atomic_unsigned_long_long * _Nonnull atomic);
|
||||
void catmc_nio_atomic_unsigned_long_long_store(struct catmc_nio_atomic_unsigned_long_long * _Nonnull atomic, unsigned long long value);
|
||||
|
||||
struct catmc_nio_atomic_int_least8_t {
|
||||
_Atomic int_least8_t value;
|
||||
};
|
||||
void catmc_nio_atomic_int_least8_t_create_with_existing_storage(struct catmc_nio_atomic_int_least8_t * _Nonnull storage, int_least8_t value);
|
||||
bool catmc_nio_atomic_int_least8_t_compare_and_exchange(struct catmc_nio_atomic_int_least8_t * _Nonnull atomic, int_least8_t expected, int_least8_t desired);
|
||||
int_least8_t catmc_nio_atomic_int_least8_t_add(struct catmc_nio_atomic_int_least8_t * _Nonnull atomic, int_least8_t value);
|
||||
int_least8_t catmc_nio_atomic_int_least8_t_sub(struct catmc_nio_atomic_int_least8_t * _Nonnull atomic, int_least8_t value);
|
||||
int_least8_t catmc_nio_atomic_int_least8_t_exchange(struct catmc_nio_atomic_int_least8_t * _Nonnull atomic, int_least8_t value);
|
||||
int_least8_t catmc_nio_atomic_int_least8_t_load(struct catmc_nio_atomic_int_least8_t * _Nonnull atomic);
|
||||
void catmc_nio_atomic_int_least8_t_store(struct catmc_nio_atomic_int_least8_t * _Nonnull atomic, int_least8_t value);
|
||||
|
||||
struct catmc_nio_atomic_uint_least8_t {
|
||||
_Atomic uint_least8_t value;
|
||||
};
|
||||
void catmc_nio_atomic_uint_least8_t_create_with_existing_storage(struct catmc_nio_atomic_uint_least8_t * _Nonnull storage, uint_least8_t value);
|
||||
bool catmc_nio_atomic_uint_least8_t_compare_and_exchange(struct catmc_nio_atomic_uint_least8_t * _Nonnull atomic, uint_least8_t expected, uint_least8_t desired);
|
||||
uint_least8_t catmc_nio_atomic_uint_least8_t_add(struct catmc_nio_atomic_uint_least8_t * _Nonnull atomic, uint_least8_t value);
|
||||
uint_least8_t catmc_nio_atomic_uint_least8_t_sub(struct catmc_nio_atomic_uint_least8_t * _Nonnull atomic, uint_least8_t value);
|
||||
uint_least8_t catmc_nio_atomic_uint_least8_t_exchange(struct catmc_nio_atomic_uint_least8_t * _Nonnull atomic, uint_least8_t value);
|
||||
uint_least8_t catmc_nio_atomic_uint_least8_t_load(struct catmc_nio_atomic_uint_least8_t * _Nonnull atomic);
|
||||
void catmc_nio_atomic_uint_least8_t_store(struct catmc_nio_atomic_uint_least8_t * _Nonnull atomic, uint_least8_t value);
|
||||
|
||||
struct catmc_nio_atomic_int_least16_t {
|
||||
_Atomic int_least16_t value;
|
||||
};
|
||||
void catmc_nio_atomic_int_least16_t_create_with_existing_storage(struct catmc_nio_atomic_int_least16_t * _Nonnull storage, int_least16_t value);
|
||||
bool catmc_nio_atomic_int_least16_t_compare_and_exchange(struct catmc_nio_atomic_int_least16_t * _Nonnull atomic, int_least16_t expected, int_least16_t desired);
|
||||
int_least16_t catmc_nio_atomic_int_least16_t_add(struct catmc_nio_atomic_int_least16_t * _Nonnull atomic, int_least16_t value);
|
||||
int_least16_t catmc_nio_atomic_int_least16_t_sub(struct catmc_nio_atomic_int_least16_t * _Nonnull atomic, int_least16_t value);
|
||||
int_least16_t catmc_nio_atomic_int_least16_t_exchange(struct catmc_nio_atomic_int_least16_t * _Nonnull atomic, int_least16_t value);
|
||||
int_least16_t catmc_nio_atomic_int_least16_t_load(struct catmc_nio_atomic_int_least16_t * _Nonnull atomic);
|
||||
void catmc_nio_atomic_int_least16_t_store(struct catmc_nio_atomic_int_least16_t * _Nonnull atomic, int_least16_t value);
|
||||
|
||||
struct catmc_nio_atomic_uint_least16_t {
|
||||
_Atomic uint_least16_t value;
|
||||
};
|
||||
void catmc_nio_atomic_uint_least16_t_create_with_existing_storage(struct catmc_nio_atomic_uint_least16_t * _Nonnull storage, uint_least16_t value);
|
||||
bool catmc_nio_atomic_uint_least16_t_compare_and_exchange(struct catmc_nio_atomic_uint_least16_t * _Nonnull atomic, uint_least16_t expected, uint_least16_t desired);
|
||||
uint_least16_t catmc_nio_atomic_uint_least16_t_add(struct catmc_nio_atomic_uint_least16_t * _Nonnull atomic, uint_least16_t value);
|
||||
uint_least16_t catmc_nio_atomic_uint_least16_t_sub(struct catmc_nio_atomic_uint_least16_t * _Nonnull atomic, uint_least16_t value);
|
||||
uint_least16_t catmc_nio_atomic_uint_least16_t_exchange(struct catmc_nio_atomic_uint_least16_t * _Nonnull atomic, uint_least16_t value);
|
||||
uint_least16_t catmc_nio_atomic_uint_least16_t_load(struct catmc_nio_atomic_uint_least16_t * _Nonnull atomic);
|
||||
void catmc_nio_atomic_uint_least16_t_store(struct catmc_nio_atomic_uint_least16_t * _Nonnull atomic, uint_least16_t value);
|
||||
|
||||
struct catmc_nio_atomic_int_least32_t {
|
||||
_Atomic int_least32_t value;
|
||||
};
|
||||
void catmc_nio_atomic_int_least32_t_create_with_existing_storage(struct catmc_nio_atomic_int_least32_t * _Nonnull storage, int_least32_t value);
|
||||
bool catmc_nio_atomic_int_least32_t_compare_and_exchange(struct catmc_nio_atomic_int_least32_t * _Nonnull atomic, int_least32_t expected, int_least32_t desired);
|
||||
int_least32_t catmc_nio_atomic_int_least32_t_add(struct catmc_nio_atomic_int_least32_t * _Nonnull atomic, int_least32_t value);
|
||||
int_least32_t catmc_nio_atomic_int_least32_t_sub(struct catmc_nio_atomic_int_least32_t * _Nonnull atomic, int_least32_t value);
|
||||
int_least32_t catmc_nio_atomic_int_least32_t_exchange(struct catmc_nio_atomic_int_least32_t * _Nonnull atomic, int_least32_t value);
|
||||
int_least32_t catmc_nio_atomic_int_least32_t_load(struct catmc_nio_atomic_int_least32_t * _Nonnull atomic);
|
||||
void catmc_nio_atomic_int_least32_t_store(struct catmc_nio_atomic_int_least32_t * _Nonnull atomic, int_least32_t value);
|
||||
|
||||
struct catmc_nio_atomic_uint_least32_t {
|
||||
_Atomic uint_least32_t value;
|
||||
};
|
||||
void catmc_nio_atomic_uint_least32_t_create_with_existing_storage(struct catmc_nio_atomic_uint_least32_t * _Nonnull storage, uint_least32_t value);
|
||||
bool catmc_nio_atomic_uint_least32_t_compare_and_exchange(struct catmc_nio_atomic_uint_least32_t * _Nonnull atomic, uint_least32_t expected, uint_least32_t desired);
|
||||
uint_least32_t catmc_nio_atomic_uint_least32_t_add(struct catmc_nio_atomic_uint_least32_t * _Nonnull atomic, uint_least32_t value);
|
||||
uint_least32_t catmc_nio_atomic_uint_least32_t_sub(struct catmc_nio_atomic_uint_least32_t * _Nonnull atomic, uint_least32_t value);
|
||||
uint_least32_t catmc_nio_atomic_uint_least32_t_exchange(struct catmc_nio_atomic_uint_least32_t * _Nonnull atomic, uint_least32_t value);
|
||||
uint_least32_t catmc_nio_atomic_uint_least32_t_load(struct catmc_nio_atomic_uint_least32_t * _Nonnull atomic);
|
||||
void catmc_nio_atomic_uint_least32_t_store(struct catmc_nio_atomic_uint_least32_t * _Nonnull atomic, uint_least32_t value);
|
||||
|
||||
struct catmc_nio_atomic_int_least64_t {
|
||||
_Atomic int_least64_t value;
|
||||
};
|
||||
void catmc_nio_atomic_int_least64_t_create_with_existing_storage(struct catmc_nio_atomic_int_least64_t * _Nonnull storage, int_least64_t value);
|
||||
bool catmc_nio_atomic_int_least64_t_compare_and_exchange(struct catmc_nio_atomic_int_least64_t * _Nonnull atomic, int_least64_t expected, int_least64_t desired);
|
||||
int_least64_t catmc_nio_atomic_int_least64_t_add(struct catmc_nio_atomic_int_least64_t * _Nonnull atomic, int_least64_t value);
|
||||
int_least64_t catmc_nio_atomic_int_least64_t_sub(struct catmc_nio_atomic_int_least64_t * _Nonnull atomic, int_least64_t value);
|
||||
int_least64_t catmc_nio_atomic_int_least64_t_exchange(struct catmc_nio_atomic_int_least64_t * _Nonnull atomic, int_least64_t value);
|
||||
int_least64_t catmc_nio_atomic_int_least64_t_load(struct catmc_nio_atomic_int_least64_t * _Nonnull atomic);
|
||||
void catmc_nio_atomic_int_least64_t_store(struct catmc_nio_atomic_int_least64_t * _Nonnull atomic, int_least64_t value);
|
||||
|
||||
struct catmc_nio_atomic_uint_least64_t {
|
||||
_Atomic uint_least64_t value;
|
||||
};
|
||||
void catmc_nio_atomic_uint_least64_t_create_with_existing_storage(struct catmc_nio_atomic_uint_least64_t * _Nonnull storage, uint_least64_t value);
|
||||
bool catmc_nio_atomic_uint_least64_t_compare_and_exchange(struct catmc_nio_atomic_uint_least64_t * _Nonnull atomic, uint_least64_t expected, uint_least64_t desired);
|
||||
uint_least64_t catmc_nio_atomic_uint_least64_t_add(struct catmc_nio_atomic_uint_least64_t * _Nonnull atomic, uint_least64_t value);
|
||||
uint_least64_t catmc_nio_atomic_uint_least64_t_sub(struct catmc_nio_atomic_uint_least64_t * _Nonnull atomic, uint_least64_t value);
|
||||
uint_least64_t catmc_nio_atomic_uint_least64_t_exchange(struct catmc_nio_atomic_uint_least64_t * _Nonnull atomic, uint_least64_t value);
|
||||
uint_least64_t catmc_nio_atomic_uint_least64_t_load(struct catmc_nio_atomic_uint_least64_t * _Nonnull atomic);
|
||||
void catmc_nio_atomic_uint_least64_t_store(struct catmc_nio_atomic_uint_least64_t * _Nonnull atomic, uint_least64_t value);
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the SwiftNIO open source project
|
||||
//
|
||||
// Copyright (c) 2017-2019 Apple Inc. and the SwiftNIO project authors
|
||||
// Licensed under Apache License v2.0
|
||||
//
|
||||
// See LICENSE.txt for license information
|
||||
// See CONTRIBUTORS.txt for the list of SwiftNIO project authors
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdatomic.h>
|
||||
#include <stdbool.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../include/CNIOAtomics.h"
|
||||
#include "cpp_magic.h"
|
||||
|
||||
#define MAKE(type) /*
|
||||
*/ void catmc_nio_atomic_##type##_create_with_existing_storage(struct catmc_nio_atomic_##type *storage, type value) { /*
|
||||
*/ atomic_init(&storage->value, value); /*
|
||||
*/ } /*
|
||||
*/ /*
|
||||
*/ bool catmc_nio_atomic_##type##_compare_and_exchange(struct catmc_nio_atomic_##type *wrapper, type expected, type desired) { /*
|
||||
*/ type expected_copy = expected; /*
|
||||
*/ return atomic_compare_exchange_strong(&wrapper->value, &expected_copy, desired); /*
|
||||
*/ } /*
|
||||
*/ /*
|
||||
*/ type catmc_nio_atomic_##type##_add(struct catmc_nio_atomic_##type *wrapper, type value) { /*
|
||||
*/ return atomic_fetch_add_explicit(&wrapper->value, value, memory_order_relaxed); /*
|
||||
*/ } /*
|
||||
*/ /*
|
||||
*/ type catmc_nio_atomic_##type##_sub(struct catmc_nio_atomic_##type *wrapper, type value) { /*
|
||||
*/ return atomic_fetch_sub_explicit(&wrapper->value, value, memory_order_relaxed); /*
|
||||
*/ } /*
|
||||
*/ /*
|
||||
*/ type catmc_nio_atomic_##type##_exchange(struct catmc_nio_atomic_##type *wrapper, type value) { /*
|
||||
*/ return atomic_exchange_explicit(&wrapper->value, value, memory_order_relaxed); /*
|
||||
*/ } /*
|
||||
*/ /*
|
||||
*/ type catmc_nio_atomic_##type##_load(struct catmc_nio_atomic_##type *wrapper) { /*
|
||||
*/ return atomic_load_explicit(&wrapper->value, memory_order_relaxed); /*
|
||||
*/ } /*
|
||||
*/ /*
|
||||
*/ void catmc_nio_atomic_##type##_store(struct catmc_nio_atomic_##type *wrapper, type value) { /*
|
||||
*/ atomic_store_explicit(&wrapper->value, value, memory_order_relaxed); /*
|
||||
*/ }
|
||||
|
||||
typedef signed char signed_char;
|
||||
typedef signed short signed_short;
|
||||
typedef signed int signed_int;
|
||||
typedef signed long signed_long;
|
||||
typedef signed long long signed_long_long;
|
||||
typedef unsigned char unsigned_char;
|
||||
typedef unsigned short unsigned_short;
|
||||
typedef unsigned int unsigned_int;
|
||||
typedef unsigned long unsigned_long;
|
||||
typedef unsigned long long unsigned_long_long;
|
||||
typedef long long long_long;
|
||||
|
||||
MAP(MAKE,EMPTY,
|
||||
bool,
|
||||
char, short, int, long, long_long,
|
||||
signed_char, signed_short, signed_int, signed_long, signed_long_long,
|
||||
unsigned_char, unsigned_short, unsigned_int, unsigned_long, unsigned_long_long,
|
||||
int_least8_t, uint_least8_t,
|
||||
int_least16_t, uint_least16_t,
|
||||
int_least32_t, uint_least32_t,
|
||||
int_least64_t, uint_least64_t
|
||||
)
|
|
@ -34,7 +34,7 @@ private struct SocketChannelLifecycleManager {
|
|||
// MARK: properties
|
||||
private let eventLoop: EventLoop
|
||||
// this is queried from the Channel, ie. must be thread-safe
|
||||
internal let isActiveAtomic: Atomic<Bool>
|
||||
internal let isActiveAtomic: NIOAtomic<Bool>
|
||||
// these are only to be accessed on the EventLoop
|
||||
|
||||
// have we seen the `.readEOF` notification
|
||||
|
@ -57,7 +57,7 @@ private struct SocketChannelLifecycleManager {
|
|||
|
||||
// MARK: API
|
||||
// isActiveAtomic needs to be injected as it's accessed from arbitrary threads and `SocketChannelLifecycleManager` is usually held mutable
|
||||
internal init(eventLoop: EventLoop, isActiveAtomic: Atomic<Bool>) {
|
||||
internal init(eventLoop: EventLoop, isActiveAtomic: NIOAtomic<Bool>) {
|
||||
self.eventLoop = eventLoop
|
||||
self.isActiveAtomic = isActiveAtomic
|
||||
}
|
||||
|
@ -213,7 +213,7 @@ class BaseSocketChannel<SocketType: BaseSocketProtocol>: SelectableChannel, Chan
|
|||
internal let selectableEventLoop: SelectableEventLoop
|
||||
private let addressesCached: AtomicBox<Box<(local:SocketAddress?, remote:SocketAddress?)>> = AtomicBox(value: Box((local: nil, remote: nil)))
|
||||
private let bufferAllocatorCached: AtomicBox<Box<ByteBufferAllocator>>
|
||||
private let isActiveAtomic: Atomic<Bool> = Atomic(value: false)
|
||||
private let isActiveAtomic: NIOAtomic<Bool> = .makeAtomic(value: false)
|
||||
private var _pipeline: ChannelPipeline! = nil // this is really a constant (set in .init) but needs `self` to be constructed and therefore a `var`. Do not change as this needs to accessed from arbitrary threads
|
||||
// just a thread-safe way of having something to print about the socket from any thread
|
||||
internal let socketDescription: String
|
||||
|
|
|
@ -1128,7 +1128,7 @@ extension EventLoopGroup {
|
|||
}
|
||||
}
|
||||
|
||||
private let nextEventLoopGroupID = Atomic(value: 0)
|
||||
private let nextEventLoopGroupID = NIOAtomic.makeAtomic(value: 0)
|
||||
|
||||
/// Called per `NIOThread` that is created for an EventLoop to do custom initialization of the `NIOThread` before the actual `EventLoop` is run on it.
|
||||
typealias ThreadInitializer = (NIOThread) -> Void
|
||||
|
@ -1156,7 +1156,7 @@ public final class MultiThreadedEventLoopGroup: EventLoopGroup {
|
|||
|
||||
private static let threadSpecificEventLoop = ThreadSpecificVariable<SelectableEventLoop>()
|
||||
|
||||
private let index = Atomic<Int>(value: 0)
|
||||
private let index = NIOAtomic<Int>.makeAtomic(value: 0)
|
||||
private let eventLoops: [SelectableEventLoop]
|
||||
private let shutdownLock: Lock = Lock()
|
||||
private var runState: RunState = .running
|
||||
|
|
|
@ -360,7 +360,7 @@ final class PendingDatagramWritesManager: PendingWritesManager {
|
|||
private var state = PendingDatagramWritesState()
|
||||
|
||||
internal var waterMark: ChannelOptions.Types.WriteBufferWaterMark = ChannelOptions.Types.WriteBufferWaterMark(low: 32 * 1024, high: 64 * 1024)
|
||||
internal let channelWritabilityFlag: Atomic<Bool> = Atomic(value: true)
|
||||
internal let channelWritabilityFlag: NIOAtomic<Bool> = .makeAtomic(value: true)
|
||||
internal var writeSpinCount: UInt = 16
|
||||
private(set) var isOpen = true
|
||||
|
||||
|
|
|
@ -277,7 +277,7 @@ final class PendingStreamWritesManager: PendingWritesManager {
|
|||
private var storageRefs: UnsafeMutableBufferPointer<Unmanaged<AnyObject>>
|
||||
|
||||
internal var waterMark: ChannelOptions.Types.WriteBufferWaterMark = ChannelOptions.Types.WriteBufferWaterMark(low: 32 * 1024, high: 64 * 1024)
|
||||
internal let channelWritabilityFlag: Atomic<Bool> = Atomic(value: true)
|
||||
internal let channelWritabilityFlag: NIOAtomic<Bool> = .makeAtomic(value: true)
|
||||
|
||||
internal var writeSpinCount: UInt = 16
|
||||
|
||||
|
@ -451,7 +451,7 @@ internal protocol PendingWritesManager {
|
|||
var isFlushPending: Bool { get }
|
||||
var writeSpinCount: UInt { get }
|
||||
var currentBestWriteMechanism: WriteMechanism { get }
|
||||
var channelWritabilityFlag: Atomic<Bool> { get }
|
||||
var channelWritabilityFlag: NIOAtomic<Bool> { get }
|
||||
}
|
||||
|
||||
extension PendingWritesManager {
|
||||
|
|
|
@ -0,0 +1,287 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the SwiftNIO open source project
|
||||
//
|
||||
// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors
|
||||
// Licensed under Apache License v2.0
|
||||
//
|
||||
// See LICENSE.txt for license information
|
||||
// See CONTRIBUTORS.txt for the list of SwiftNIO project authors
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import CNIOAtomics
|
||||
|
||||
/// The protocol that all types that can be made atomic must conform to.
|
||||
///
|
||||
/// **Do not add conformance to this protocol for arbitrary types**. Only a small range
|
||||
/// of types have appropriate atomic operations supported by the CPU, and those types
|
||||
/// already have conformances implemented.
|
||||
public protocol NIOAtomicPrimitive {
|
||||
associatedtype AtomicWrapper
|
||||
static var nio_atomic_create_with_existing_storage: (UnsafeMutablePointer<AtomicWrapper>, Self) -> Void { get }
|
||||
static var nio_atomic_compare_and_exchange: (UnsafeMutablePointer<AtomicWrapper>, Self, Self) -> Bool { get }
|
||||
static var nio_atomic_add: (UnsafeMutablePointer<AtomicWrapper>, Self) -> Self { get }
|
||||
static var nio_atomic_sub: (UnsafeMutablePointer<AtomicWrapper>, Self) -> Self { get }
|
||||
static var nio_atomic_exchange: (UnsafeMutablePointer<AtomicWrapper>, Self) -> Self { get }
|
||||
static var nio_atomic_load: (UnsafeMutablePointer<AtomicWrapper>) -> Self { get }
|
||||
static var nio_atomic_store: (UnsafeMutablePointer<AtomicWrapper>, Self) -> Void { get }
|
||||
}
|
||||
|
||||
extension Bool: NIOAtomicPrimitive {
|
||||
public typealias AtomicWrapper = catmc_nio_atomic__Bool
|
||||
public static let nio_atomic_create_with_existing_storage = catmc_nio_atomic__Bool_create_with_existing_storage
|
||||
public static let nio_atomic_compare_and_exchange = catmc_nio_atomic__Bool_compare_and_exchange
|
||||
public static let nio_atomic_add = catmc_nio_atomic__Bool_add
|
||||
public static let nio_atomic_sub = catmc_nio_atomic__Bool_sub
|
||||
public static let nio_atomic_exchange = catmc_nio_atomic__Bool_exchange
|
||||
public static let nio_atomic_load = catmc_nio_atomic__Bool_load
|
||||
public static let nio_atomic_store = catmc_nio_atomic__Bool_store
|
||||
}
|
||||
|
||||
extension Int8: NIOAtomicPrimitive {
|
||||
public typealias AtomicWrapper = catmc_nio_atomic_int_least8_t
|
||||
public static let nio_atomic_create_with_existing_storage = catmc_nio_atomic_int_least8_t_create_with_existing_storage
|
||||
public static let nio_atomic_compare_and_exchange = catmc_nio_atomic_int_least8_t_compare_and_exchange
|
||||
public static let nio_atomic_add = catmc_nio_atomic_int_least8_t_add
|
||||
public static let nio_atomic_sub = catmc_nio_atomic_int_least8_t_sub
|
||||
public static let nio_atomic_exchange = catmc_nio_atomic_int_least8_t_exchange
|
||||
public static let nio_atomic_load = catmc_nio_atomic_int_least8_t_load
|
||||
public static let nio_atomic_store = catmc_nio_atomic_int_least8_t_store
|
||||
}
|
||||
|
||||
extension UInt8: NIOAtomicPrimitive {
|
||||
public typealias AtomicWrapper = catmc_nio_atomic_uint_least8_t
|
||||
public static let nio_atomic_create_with_existing_storage = catmc_nio_atomic_uint_least8_t_create_with_existing_storage
|
||||
public static let nio_atomic_compare_and_exchange = catmc_nio_atomic_uint_least8_t_compare_and_exchange
|
||||
public static let nio_atomic_add = catmc_nio_atomic_uint_least8_t_add
|
||||
public static let nio_atomic_sub = catmc_nio_atomic_uint_least8_t_sub
|
||||
public static let nio_atomic_exchange = catmc_nio_atomic_uint_least8_t_exchange
|
||||
public static let nio_atomic_load = catmc_nio_atomic_uint_least8_t_load
|
||||
public static let nio_atomic_store = catmc_nio_atomic_uint_least8_t_store
|
||||
}
|
||||
|
||||
extension Int16: NIOAtomicPrimitive {
|
||||
public typealias AtomicWrapper = catmc_nio_atomic_int_least16_t
|
||||
public static let nio_atomic_create_with_existing_storage = catmc_nio_atomic_int_least16_t_create_with_existing_storage
|
||||
public static let nio_atomic_compare_and_exchange = catmc_nio_atomic_int_least16_t_compare_and_exchange
|
||||
public static let nio_atomic_add = catmc_nio_atomic_int_least16_t_add
|
||||
public static let nio_atomic_sub = catmc_nio_atomic_int_least16_t_sub
|
||||
public static let nio_atomic_exchange = catmc_nio_atomic_int_least16_t_exchange
|
||||
public static let nio_atomic_load = catmc_nio_atomic_int_least16_t_load
|
||||
public static let nio_atomic_store = catmc_nio_atomic_int_least16_t_store
|
||||
}
|
||||
|
||||
extension UInt16: NIOAtomicPrimitive {
|
||||
public typealias AtomicWrapper = catmc_nio_atomic_uint_least16_t
|
||||
public static let nio_atomic_create_with_existing_storage = catmc_nio_atomic_uint_least16_t_create_with_existing_storage
|
||||
public static let nio_atomic_compare_and_exchange = catmc_nio_atomic_uint_least16_t_compare_and_exchange
|
||||
public static let nio_atomic_add = catmc_nio_atomic_uint_least16_t_add
|
||||
public static let nio_atomic_sub = catmc_nio_atomic_uint_least16_t_sub
|
||||
public static let nio_atomic_exchange = catmc_nio_atomic_uint_least16_t_exchange
|
||||
public static let nio_atomic_load = catmc_nio_atomic_uint_least16_t_load
|
||||
public static let nio_atomic_store = catmc_nio_atomic_uint_least16_t_store
|
||||
}
|
||||
|
||||
extension Int32: NIOAtomicPrimitive {
|
||||
public typealias AtomicWrapper = catmc_nio_atomic_int_least32_t
|
||||
public static let nio_atomic_create_with_existing_storage = catmc_nio_atomic_int_least32_t_create_with_existing_storage
|
||||
public static let nio_atomic_compare_and_exchange = catmc_nio_atomic_int_least32_t_compare_and_exchange
|
||||
public static let nio_atomic_add = catmc_nio_atomic_int_least32_t_add
|
||||
public static let nio_atomic_sub = catmc_nio_atomic_int_least32_t_sub
|
||||
public static let nio_atomic_exchange = catmc_nio_atomic_int_least32_t_exchange
|
||||
public static let nio_atomic_load = catmc_nio_atomic_int_least32_t_load
|
||||
public static let nio_atomic_store = catmc_nio_atomic_int_least32_t_store
|
||||
}
|
||||
|
||||
extension UInt32: NIOAtomicPrimitive {
|
||||
public typealias AtomicWrapper = catmc_nio_atomic_uint_least32_t
|
||||
public static let nio_atomic_create_with_existing_storage = catmc_nio_atomic_uint_least32_t_create_with_existing_storage
|
||||
public static let nio_atomic_compare_and_exchange = catmc_nio_atomic_uint_least32_t_compare_and_exchange
|
||||
public static let nio_atomic_add = catmc_nio_atomic_uint_least32_t_add
|
||||
public static let nio_atomic_sub = catmc_nio_atomic_uint_least32_t_sub
|
||||
public static let nio_atomic_exchange = catmc_nio_atomic_uint_least32_t_exchange
|
||||
public static let nio_atomic_load = catmc_nio_atomic_uint_least32_t_load
|
||||
public static let nio_atomic_store = catmc_nio_atomic_uint_least32_t_store
|
||||
}
|
||||
|
||||
extension Int64: NIOAtomicPrimitive {
|
||||
public typealias AtomicWrapper = catmc_nio_atomic_long_long
|
||||
public static let nio_atomic_create_with_existing_storage = catmc_nio_atomic_long_long_create_with_existing_storage
|
||||
public static let nio_atomic_compare_and_exchange = catmc_nio_atomic_long_long_compare_and_exchange
|
||||
public static let nio_atomic_add = catmc_nio_atomic_long_long_add
|
||||
public static let nio_atomic_sub = catmc_nio_atomic_long_long_sub
|
||||
public static let nio_atomic_exchange = catmc_nio_atomic_long_long_exchange
|
||||
public static let nio_atomic_load = catmc_nio_atomic_long_long_load
|
||||
public static let nio_atomic_store = catmc_nio_atomic_long_long_store
|
||||
}
|
||||
|
||||
extension UInt64: NIOAtomicPrimitive {
|
||||
public typealias AtomicWrapper = catmc_nio_atomic_unsigned_long_long
|
||||
public static let nio_atomic_create_with_existing_storage = catmc_nio_atomic_unsigned_long_long_create_with_existing_storage
|
||||
public static let nio_atomic_compare_and_exchange = catmc_nio_atomic_unsigned_long_long_compare_and_exchange
|
||||
public static let nio_atomic_add = catmc_nio_atomic_unsigned_long_long_add
|
||||
public static let nio_atomic_sub = catmc_nio_atomic_unsigned_long_long_sub
|
||||
public static let nio_atomic_exchange = catmc_nio_atomic_unsigned_long_long_exchange
|
||||
public static let nio_atomic_load = catmc_nio_atomic_unsigned_long_long_load
|
||||
public static let nio_atomic_store = catmc_nio_atomic_unsigned_long_long_store
|
||||
}
|
||||
|
||||
extension Int: NIOAtomicPrimitive {
|
||||
public typealias AtomicWrapper = catmc_nio_atomic_long
|
||||
public static let nio_atomic_create_with_existing_storage = catmc_nio_atomic_long_create_with_existing_storage
|
||||
public static let nio_atomic_compare_and_exchange = catmc_nio_atomic_long_compare_and_exchange
|
||||
public static let nio_atomic_add = catmc_nio_atomic_long_add
|
||||
public static let nio_atomic_sub = catmc_nio_atomic_long_sub
|
||||
public static let nio_atomic_exchange = catmc_nio_atomic_long_exchange
|
||||
public static let nio_atomic_load = catmc_nio_atomic_long_load
|
||||
public static let nio_atomic_store = catmc_nio_atomic_long_store
|
||||
}
|
||||
|
||||
extension UInt: NIOAtomicPrimitive {
|
||||
public typealias AtomicWrapper = catmc_nio_atomic_unsigned_long
|
||||
public static let nio_atomic_create_with_existing_storage = catmc_nio_atomic_unsigned_long_create_with_existing_storage
|
||||
public static let nio_atomic_compare_and_exchange = catmc_nio_atomic_unsigned_long_compare_and_exchange
|
||||
public static let nio_atomic_add = catmc_nio_atomic_unsigned_long_add
|
||||
public static let nio_atomic_sub = catmc_nio_atomic_unsigned_long_sub
|
||||
public static let nio_atomic_exchange = catmc_nio_atomic_unsigned_long_exchange
|
||||
public static let nio_atomic_load = catmc_nio_atomic_unsigned_long_load
|
||||
public static let nio_atomic_store = catmc_nio_atomic_unsigned_long_store
|
||||
}
|
||||
|
||||
/// An encapsulation of an atomic primitive object.
|
||||
///
|
||||
/// Atomic objects support a wide range of atomic operations:
|
||||
///
|
||||
/// - Compare and swap
|
||||
/// - Add
|
||||
/// - Subtract
|
||||
/// - Exchange
|
||||
/// - Load current value
|
||||
/// - Store current value
|
||||
///
|
||||
/// Atomic primitives are useful when building constructs that need to
|
||||
/// communicate or cooperate across multiple threads. In the case of
|
||||
/// SwiftNIO this usually involves communicating across multiple event loops.
|
||||
///
|
||||
/// By necessity, all atomic values are references: after all, it makes no
|
||||
/// sense to talk about managing an atomic value when each time it's modified
|
||||
/// the thread that modified it gets a local copy!
|
||||
public final class NIOAtomic<T: NIOAtomicPrimitive> {
|
||||
@usableFromInline
|
||||
typealias Manager = ManagedBufferPointer<Void, T.AtomicWrapper>
|
||||
|
||||
/// Create an atomic object with `value`
|
||||
@inlinable
|
||||
public static func makeAtomic(value: T) -> NIOAtomic {
|
||||
let manager = Manager(bufferClass: self, minimumCapacity: 1) { _, _ in }
|
||||
manager.withUnsafeMutablePointerToElements {
|
||||
T.nio_atomic_create_with_existing_storage($0, value)
|
||||
}
|
||||
return manager.buffer as! NIOAtomic<T>
|
||||
}
|
||||
|
||||
/// Atomically compares the value against `expected` and, if they are equal,
|
||||
/// replaces the value with `desired`.
|
||||
///
|
||||
/// This implementation conforms to C11's `atomic_compare_exchange_strong`. This
|
||||
/// means that the compare-and-swap will always succeed if `expected` is equal to
|
||||
/// value. Additionally, it uses a *sequentially consistent ordering*. For more
|
||||
/// details on atomic memory models, check the documentation for C11's
|
||||
/// `stdatomic.h`.
|
||||
///
|
||||
/// - Parameter expected: The value that this object must currently hold for the
|
||||
/// compare-and-swap to succeed.
|
||||
/// - Parameter desired: The new value that this object will hold if the compare
|
||||
/// succeeds.
|
||||
/// - Returns: `True` if the exchange occurred, or `False` if `expected` did not
|
||||
/// match the current value and so no exchange occurred.
|
||||
@inlinable
|
||||
public func compareAndExchange(expected: T, desired: T) -> Bool {
|
||||
return Manager(unsafeBufferObject: self).withUnsafeMutablePointerToElements {
|
||||
return T.nio_atomic_compare_and_exchange($0, expected, desired)
|
||||
}
|
||||
}
|
||||
|
||||
/// Atomically adds `rhs` to this object.
|
||||
///
|
||||
/// This implementation uses a *relaxed* memory ordering. This guarantees nothing
|
||||
/// more than that this operation is atomic: there is no guarantee that any other
|
||||
/// event will be ordered before or after this one.
|
||||
///
|
||||
/// - Parameter rhs: The value to add to this object.
|
||||
/// - Returns: The previous value of this object, before the addition occurred.
|
||||
@inlinable
|
||||
public func add(_ rhs: T) -> T {
|
||||
return Manager(unsafeBufferObject: self).withUnsafeMutablePointerToElements {
|
||||
return T.nio_atomic_add($0, rhs)
|
||||
}
|
||||
}
|
||||
|
||||
/// Atomically subtracts `rhs` from this object.
|
||||
///
|
||||
/// This implementation uses a *relaxed* memory ordering. This guarantees nothing
|
||||
/// more than that this operation is atomic: there is no guarantee that any other
|
||||
/// event will be ordered before or after this one.
|
||||
///
|
||||
/// - Parameter rhs: The value to subtract from this object.
|
||||
/// - Returns: The previous value of this object, before the subtraction occurred.
|
||||
@inlinable
|
||||
public func sub(_ rhs: T) -> T {
|
||||
return Manager(unsafeBufferObject: self).withUnsafeMutablePointerToElements {
|
||||
return T.nio_atomic_sub($0, rhs)
|
||||
}
|
||||
}
|
||||
|
||||
/// Atomically exchanges `value` for the current value of this object.
|
||||
///
|
||||
/// This implementation uses a *relaxed* memory ordering. This guarantees nothing
|
||||
/// more than that this operation is atomic: there is no guarantee that any other
|
||||
/// event will be ordered before or after this one.
|
||||
///
|
||||
/// - Parameter value: The new value to set this object to.
|
||||
/// - Returns: The value previously held by this object.
|
||||
@inlinable
|
||||
public func exchange(with value: T) -> T {
|
||||
return Manager(unsafeBufferObject: self).withUnsafeMutablePointerToElements {
|
||||
return T.nio_atomic_exchange($0, value)
|
||||
}
|
||||
}
|
||||
|
||||
/// Atomically loads and returns the value of this object.
|
||||
///
|
||||
/// This implementation uses a *relaxed* memory ordering. This guarantees nothing
|
||||
/// more than that this operation is atomic: there is no guarantee that any other
|
||||
/// event will be ordered before or after this one.
|
||||
///
|
||||
/// - Returns: The value of this object
|
||||
@inlinable
|
||||
public func load() -> T {
|
||||
return Manager(unsafeBufferObject: self).withUnsafeMutablePointerToElements {
|
||||
return T.nio_atomic_load($0)
|
||||
}
|
||||
}
|
||||
|
||||
/// Atomically replaces the value of this object with `value`.
|
||||
///
|
||||
/// This implementation uses a *relaxed* memory ordering. This guarantees nothing
|
||||
/// more than that this operation is atomic: there is no guarantee that any other
|
||||
/// event will be ordered before or after this one.
|
||||
///
|
||||
/// - Parameter value: The new value to set the object to.
|
||||
@inlinable
|
||||
public func store(_ value: T) -> Void {
|
||||
return Manager(unsafeBufferObject: self).withUnsafeMutablePointerToElements {
|
||||
return T.nio_atomic_store($0, value)
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
Manager(unsafeBufferObject: self).withUnsafeMutablePointers { headerPtr, elementsPtr in
|
||||
elementsPtr.deinitialize(count: 1)
|
||||
headerPtr.deinitialize(count: 1)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -153,6 +153,7 @@ public struct UnsafeEmbeddedAtomic<T: AtomicPrimitive> {
|
|||
/// By necessity, all atomic values are references: after all, it makes no
|
||||
/// sense to talk about managing an atomic value when each time it's modified
|
||||
/// the thread that modified it gets a local copy!
|
||||
@available(*, deprecated, message:"please use NIOAtomic instead")
|
||||
public final class Atomic<T: AtomicPrimitive> {
|
||||
@usableFromInline
|
||||
internal let embedded: UnsafeEmbeddedAtomic<T>
|
||||
|
@ -392,11 +393,11 @@ extension UInt: AtomicPrimitive {
|
|||
///
|
||||
/// It behaves very much like `Atomic<T>` but for objects, maintaining the correct retain counts.
|
||||
public final class AtomicBox<T: AnyObject> {
|
||||
private let storage: Atomic<UInt>
|
||||
private let storage: NIOAtomic<UInt>
|
||||
|
||||
public init(value: T) {
|
||||
let ptr = Unmanaged<T>.passRetained(value)
|
||||
self.storage = Atomic(value: UInt(bitPattern: ptr.toOpaque()))
|
||||
self.storage = NIOAtomic.makeAtomic(value: UInt(bitPattern: ptr.toOpaque()))
|
||||
}
|
||||
|
||||
deinit {
|
||||
|
|
|
@ -24,23 +24,23 @@ import NIOConcurrencyHelpers
|
|||
/// - note: Contrary to most `ChannelHandler`s, all of `EventCounterHandler`'s API is thread-safe meaning that you can
|
||||
/// query the events received from any thread.
|
||||
public final class EventCounterHandler {
|
||||
private let _channelRegisteredCalls = Atomic<Int>(value: 0)
|
||||
private let _channelUnregisteredCalls = Atomic<Int>(value: 0)
|
||||
private let _channelActiveCalls = Atomic<Int>(value: 0)
|
||||
private let _channelInactiveCalls = Atomic<Int>(value: 0)
|
||||
private let _channelReadCalls = Atomic<Int>(value: 0)
|
||||
private let _channelReadCompleteCalls = Atomic<Int>(value: 0)
|
||||
private let _channelWritabilityChangedCalls = Atomic<Int>(value: 0)
|
||||
private let _userInboundEventTriggeredCalls = Atomic<Int>(value: 0)
|
||||
private let _errorCaughtCalls = Atomic<Int>(value: 0)
|
||||
private let _registerCalls = Atomic<Int>(value: 0)
|
||||
private let _bindCalls = Atomic<Int>(value: 0)
|
||||
private let _connectCalls = Atomic<Int>(value: 0)
|
||||
private let _writeCalls = Atomic<Int>(value: 0)
|
||||
private let _flushCalls = Atomic<Int>(value: 0)
|
||||
private let _readCalls = Atomic<Int>(value: 0)
|
||||
private let _closeCalls = Atomic<Int>(value: 0)
|
||||
private let _triggerUserOutboundEventCalls = Atomic<Int>(value: 0)
|
||||
private let _channelRegisteredCalls = NIOAtomic<Int>.makeAtomic(value: 0)
|
||||
private let _channelUnregisteredCalls = NIOAtomic<Int>.makeAtomic(value: 0)
|
||||
private let _channelActiveCalls = NIOAtomic<Int>.makeAtomic(value: 0)
|
||||
private let _channelInactiveCalls = NIOAtomic<Int>.makeAtomic(value: 0)
|
||||
private let _channelReadCalls = NIOAtomic<Int>.makeAtomic(value: 0)
|
||||
private let _channelReadCompleteCalls = NIOAtomic<Int>.makeAtomic(value: 0)
|
||||
private let _channelWritabilityChangedCalls = NIOAtomic<Int>.makeAtomic(value: 0)
|
||||
private let _userInboundEventTriggeredCalls = NIOAtomic<Int>.makeAtomic(value: 0)
|
||||
private let _errorCaughtCalls = NIOAtomic<Int>.makeAtomic(value: 0)
|
||||
private let _registerCalls = NIOAtomic<Int>.makeAtomic(value: 0)
|
||||
private let _bindCalls = NIOAtomic<Int>.makeAtomic(value: 0)
|
||||
private let _connectCalls = NIOAtomic<Int>.makeAtomic(value: 0)
|
||||
private let _writeCalls = NIOAtomic<Int>.makeAtomic(value: 0)
|
||||
private let _flushCalls = NIOAtomic<Int>.makeAtomic(value: 0)
|
||||
private let _readCalls = NIOAtomic<Int>.makeAtomic(value: 0)
|
||||
private let _closeCalls = NIOAtomic<Int>.makeAtomic(value: 0)
|
||||
private let _triggerUserOutboundEventCalls = NIOAtomic<Int>.makeAtomic(value: 0)
|
||||
|
||||
public init() {}
|
||||
}
|
||||
|
|
|
@ -35,6 +35,14 @@ extension NIOConcurrencyHelpersTests {
|
|||
("testAddSub", testAddSub),
|
||||
("testExchange", testExchange),
|
||||
("testLoadStore", testLoadStore),
|
||||
("testLargeContendedNIOAtomicSum", testLargeContendedNIOAtomicSum),
|
||||
("testCompareAndExchangeBoolNIOAtomic", testCompareAndExchangeBoolNIOAtomic),
|
||||
("testAllOperationsBoolNIOAtomic", testAllOperationsBoolNIOAtomic),
|
||||
("testCompareAndExchangeUIntsNIOAtomic", testCompareAndExchangeUIntsNIOAtomic),
|
||||
("testCompareAndExchangeIntsNIOAtomic", testCompareAndExchangeIntsNIOAtomic),
|
||||
("testAddSubNIOAtomic", testAddSubNIOAtomic),
|
||||
("testExchangeNIOAtomic", testExchangeNIOAtomic),
|
||||
("testLoadStoreNIOAtomic", testLoadStoreNIOAtomic),
|
||||
("testLockMutualExclusion", testLockMutualExclusion),
|
||||
("testWithLockMutualExclusion", testWithLockMutualExclusion),
|
||||
("testConditionLockMutualExclusion", testConditionLockMutualExclusion),
|
||||
|
|
|
@ -25,6 +25,7 @@ class NIOConcurrencyHelpersTests: XCTestCase {
|
|||
return n*(n+1)/2
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "deprecated because it tests deprecated functionality")
|
||||
func testLargeContendedAtomicSum() {
|
||||
let noAsyncs: UInt64 = 64
|
||||
let noCounts: UInt64 = 200_000
|
||||
|
@ -43,6 +44,7 @@ class NIOConcurrencyHelpersTests: XCTestCase {
|
|||
XCTAssertEqual(sumOfIntegers(until: noAsyncs) * noCounts, ai.load())
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "deprecated because it tests deprecated functionality")
|
||||
func testCompareAndExchangeBool() {
|
||||
let ab = Atomic<Bool>(value: true)
|
||||
|
||||
|
@ -56,6 +58,7 @@ class NIOConcurrencyHelpersTests: XCTestCase {
|
|||
XCTAssertTrue(ab.compareAndExchange(expected: false, desired: true))
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "deprecated because it tests deprecated functionality")
|
||||
func testAllOperationsBool() {
|
||||
let ab = Atomic<Bool>(value: false)
|
||||
XCTAssertEqual(false, ab.load())
|
||||
|
@ -72,6 +75,7 @@ class NIOConcurrencyHelpersTests: XCTestCase {
|
|||
XCTAssertFalse(ab.compareAndExchange(expected: false, desired: true))
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "deprecated because it tests deprecated functionality")
|
||||
func testCompareAndExchangeUInts() {
|
||||
func testFor<T: AtomicPrimitive & FixedWidthInteger & UnsignedInteger>(_ value: T.Type) {
|
||||
let zero: T = 0
|
||||
|
@ -102,6 +106,7 @@ class NIOConcurrencyHelpersTests: XCTestCase {
|
|||
testFor(UInt.self)
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "deprecated because it tests deprecated functionality")
|
||||
func testCompareAndExchangeInts() {
|
||||
func testFor<T: AtomicPrimitive & FixedWidthInteger & SignedInteger>(_ value: T.Type) {
|
||||
let zero: T = 0
|
||||
|
@ -133,6 +138,7 @@ class NIOConcurrencyHelpersTests: XCTestCase {
|
|||
testFor(Int.self)
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "deprecated because it tests deprecated functionality")
|
||||
func testAddSub() {
|
||||
func testFor<T: AtomicPrimitive & FixedWidthInteger>(_ value: T.Type) {
|
||||
let zero: T = 0
|
||||
|
@ -164,6 +170,7 @@ class NIOConcurrencyHelpersTests: XCTestCase {
|
|||
testFor(UInt.self)
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "deprecated because it tests deprecated functionality")
|
||||
func testExchange() {
|
||||
func testFor<T: AtomicPrimitive & FixedWidthInteger>(_ value: T.Type) {
|
||||
let zero: T = 0
|
||||
|
@ -195,6 +202,7 @@ class NIOConcurrencyHelpersTests: XCTestCase {
|
|||
testFor(UInt.self)
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "deprecated because it tests deprecated functionality")
|
||||
func testLoadStore() {
|
||||
func testFor<T: AtomicPrimitive & FixedWidthInteger>(_ value: T.Type) {
|
||||
let zero: T = 0
|
||||
|
@ -220,6 +228,202 @@ class NIOConcurrencyHelpersTests: XCTestCase {
|
|||
testFor(UInt.self)
|
||||
}
|
||||
|
||||
func testLargeContendedNIOAtomicSum() {
|
||||
let noAsyncs: UInt64 = 64
|
||||
let noCounts: UInt64 = 200_000
|
||||
|
||||
let q = DispatchQueue(label: "q", attributes: .concurrent)
|
||||
let g = DispatchGroup()
|
||||
let ai = NIOConcurrencyHelpers.NIOAtomic<UInt64>.makeAtomic(value: 0)
|
||||
for thread in 1...noAsyncs {
|
||||
q.async(group: g) {
|
||||
for _ in 0..<noCounts {
|
||||
_ = ai.add(thread)
|
||||
}
|
||||
}
|
||||
}
|
||||
g.wait()
|
||||
XCTAssertEqual(sumOfIntegers(until: noAsyncs) * noCounts, ai.load())
|
||||
}
|
||||
|
||||
func testCompareAndExchangeBoolNIOAtomic() {
|
||||
let ab = NIOAtomic<Bool>.makeAtomic(value: true)
|
||||
|
||||
XCTAssertFalse(ab.compareAndExchange(expected: false, desired: false))
|
||||
XCTAssertTrue(ab.compareAndExchange(expected: true, desired: true))
|
||||
|
||||
XCTAssertFalse(ab.compareAndExchange(expected: false, desired: false))
|
||||
XCTAssertTrue(ab.compareAndExchange(expected: true, desired: false))
|
||||
|
||||
XCTAssertTrue(ab.compareAndExchange(expected: false, desired: false))
|
||||
XCTAssertTrue(ab.compareAndExchange(expected: false, desired: true))
|
||||
}
|
||||
|
||||
func testAllOperationsBoolNIOAtomic() {
|
||||
let ab = NIOAtomic<Bool>.makeAtomic(value: false)
|
||||
XCTAssertEqual(false, ab.load())
|
||||
ab.store(false)
|
||||
XCTAssertEqual(false, ab.load())
|
||||
ab.store(true)
|
||||
XCTAssertEqual(true, ab.load())
|
||||
ab.store(true)
|
||||
XCTAssertEqual(true, ab.load())
|
||||
XCTAssertEqual(true, ab.exchange(with: true))
|
||||
XCTAssertEqual(true, ab.exchange(with: false))
|
||||
XCTAssertEqual(false, ab.exchange(with: false))
|
||||
XCTAssertTrue(ab.compareAndExchange(expected: false, desired: true))
|
||||
XCTAssertFalse(ab.compareAndExchange(expected: false, desired: true))
|
||||
}
|
||||
|
||||
func testCompareAndExchangeUIntsNIOAtomic() {
|
||||
func testFor<T: NIOAtomicPrimitive & FixedWidthInteger & UnsignedInteger>(_ value: T.Type) {
|
||||
let zero: T = 0
|
||||
let max = ~zero
|
||||
|
||||
let ab = NIOAtomic<T>.makeAtomic(value: max)
|
||||
|
||||
XCTAssertFalse(ab.compareAndExchange(expected: zero, desired: zero))
|
||||
XCTAssertTrue(ab.compareAndExchange(expected: max, desired: max))
|
||||
|
||||
XCTAssertFalse(ab.compareAndExchange(expected: zero, desired: zero))
|
||||
XCTAssertTrue(ab.compareAndExchange(expected: max, desired: zero))
|
||||
|
||||
XCTAssertTrue(ab.compareAndExchange(expected: zero, desired: zero))
|
||||
XCTAssertTrue(ab.compareAndExchange(expected: zero, desired: max))
|
||||
|
||||
var counter = max
|
||||
for _ in 0..<255 {
|
||||
XCTAssertTrue(ab.compareAndExchange(expected: counter, desired: counter-1))
|
||||
counter = counter - 1
|
||||
}
|
||||
}
|
||||
|
||||
testFor(UInt8.self)
|
||||
testFor(UInt16.self)
|
||||
testFor(UInt32.self)
|
||||
testFor(UInt64.self)
|
||||
testFor(UInt.self)
|
||||
}
|
||||
|
||||
func testCompareAndExchangeIntsNIOAtomic() {
|
||||
func testFor<T: NIOAtomicPrimitive & FixedWidthInteger & SignedInteger>(_ value: T.Type) {
|
||||
let zero: T = 0
|
||||
let upperBound: T = 127
|
||||
|
||||
let ab = NIOAtomic<T>.makeAtomic(value: upperBound)
|
||||
|
||||
XCTAssertFalse(ab.compareAndExchange(expected: zero, desired: zero))
|
||||
XCTAssertTrue(ab.compareAndExchange(expected: upperBound, desired: upperBound))
|
||||
|
||||
XCTAssertFalse(ab.compareAndExchange(expected: zero, desired: zero))
|
||||
XCTAssertTrue(ab.compareAndExchange(expected: upperBound, desired: zero))
|
||||
|
||||
XCTAssertTrue(ab.compareAndExchange(expected: zero, desired: zero))
|
||||
XCTAssertTrue(ab.compareAndExchange(expected: zero, desired: upperBound))
|
||||
|
||||
var counter = upperBound
|
||||
for _ in 0..<255 {
|
||||
XCTAssertTrue(ab.compareAndExchange(expected: counter, desired: counter-1))
|
||||
XCTAssertFalse(ab.compareAndExchange(expected: counter, desired: counter))
|
||||
counter = counter - 1
|
||||
}
|
||||
}
|
||||
|
||||
testFor(Int8.self)
|
||||
testFor(Int16.self)
|
||||
testFor(Int32.self)
|
||||
testFor(Int64.self)
|
||||
testFor(Int.self)
|
||||
}
|
||||
|
||||
func testAddSubNIOAtomic() {
|
||||
func testFor<T: NIOAtomicPrimitive & FixedWidthInteger>(_ value: T.Type) {
|
||||
let zero: T = 0
|
||||
|
||||
let ab = NIOAtomic<T>.makeAtomic(value: zero)
|
||||
|
||||
XCTAssertEqual(0, ab.add(1))
|
||||
XCTAssertEqual(1, ab.add(41))
|
||||
XCTAssertEqual(42, ab.add(23))
|
||||
|
||||
XCTAssertEqual(65, ab.load())
|
||||
|
||||
XCTAssertEqual(65, ab.sub(23))
|
||||
XCTAssertEqual(42, ab.sub(41))
|
||||
XCTAssertEqual(1, ab.sub(1))
|
||||
|
||||
XCTAssertEqual(0, ab.load())
|
||||
}
|
||||
|
||||
testFor(Int8.self)
|
||||
testFor(Int16.self)
|
||||
testFor(Int32.self)
|
||||
testFor(Int64.self)
|
||||
testFor(Int.self)
|
||||
testFor(UInt8.self)
|
||||
testFor(UInt16.self)
|
||||
testFor(UInt32.self)
|
||||
testFor(UInt64.self)
|
||||
testFor(UInt.self)
|
||||
}
|
||||
|
||||
func testExchangeNIOAtomic() {
|
||||
func testFor<T: NIOAtomicPrimitive & FixedWidthInteger>(_ value: T.Type) {
|
||||
let zero: T = 0
|
||||
|
||||
let ab = NIOAtomic<T>.makeAtomic(value: zero)
|
||||
|
||||
XCTAssertEqual(0, ab.exchange(with: 1))
|
||||
XCTAssertEqual(1, ab.exchange(with: 42))
|
||||
XCTAssertEqual(42, ab.exchange(with: 65))
|
||||
|
||||
XCTAssertEqual(65, ab.load())
|
||||
|
||||
XCTAssertEqual(65, ab.exchange(with: 42))
|
||||
XCTAssertEqual(42, ab.exchange(with: 1))
|
||||
XCTAssertEqual(1, ab.exchange(with: 0))
|
||||
|
||||
XCTAssertEqual(0, ab.load())
|
||||
}
|
||||
|
||||
testFor(Int8.self)
|
||||
testFor(Int16.self)
|
||||
testFor(Int32.self)
|
||||
testFor(Int64.self)
|
||||
testFor(Int.self)
|
||||
testFor(UInt8.self)
|
||||
testFor(UInt16.self)
|
||||
testFor(UInt32.self)
|
||||
testFor(UInt64.self)
|
||||
testFor(UInt.self)
|
||||
}
|
||||
|
||||
func testLoadStoreNIOAtomic() {
|
||||
func testFor<T: NIOAtomicPrimitive & FixedWidthInteger>(_ value: T.Type) {
|
||||
let zero: T = 0
|
||||
|
||||
let ab = NIOAtomic<T>.makeAtomic(value: zero)
|
||||
|
||||
XCTAssertEqual(0, ab.load())
|
||||
ab.store(42)
|
||||
XCTAssertEqual(42, ab.load())
|
||||
ab.store(0)
|
||||
XCTAssertEqual(0, ab.load())
|
||||
}
|
||||
|
||||
testFor(Int8.self)
|
||||
testFor(Int16.self)
|
||||
testFor(Int32.self)
|
||||
testFor(Int64.self)
|
||||
testFor(Int.self)
|
||||
testFor(UInt8.self)
|
||||
testFor(UInt16.self)
|
||||
testFor(UInt32.self)
|
||||
testFor(UInt64.self)
|
||||
testFor(UInt.self)
|
||||
}
|
||||
|
||||
|
||||
func testLockMutualExclusion() {
|
||||
let l = Lock()
|
||||
|
||||
|
|
|
@ -200,7 +200,7 @@ public final class AcceptBackoffHandlerTest: XCTestCase {
|
|||
|
||||
let readCountHandler = ReadCountHandler()
|
||||
|
||||
let backoffProviderCalled = Atomic<Int>(value: 0)
|
||||
let backoffProviderCalled = NIOAtomic<Int>.makeAtomic(value: 0)
|
||||
let serverChannel = try setupChannel(group: group, readCountHandler: readCountHandler, backoffProvider: { err in
|
||||
if backoffProviderCalled.add(1) == 0 {
|
||||
return .seconds(1)
|
||||
|
|
|
@ -163,8 +163,8 @@ class ChannelPipelineTest: XCTestCase {
|
|||
}
|
||||
|
||||
private final class DummyHandler: ChannelHandler {
|
||||
let handlerAddedCalled = Atomic<Bool>(value: false)
|
||||
let handlerRemovedCalled = Atomic<Bool>(value: false)
|
||||
let handlerAddedCalled = NIOAtomic<Bool>.makeAtomic(value: false)
|
||||
let handlerRemovedCalled = NIOAtomic<Bool>.makeAtomic(value: false)
|
||||
|
||||
public func handlerAdded(context: ChannelHandlerContext) {
|
||||
handlerAddedCalled.store(true)
|
||||
|
|
|
@ -313,8 +313,8 @@ class EchoServerClientTest : XCTestCase {
|
|||
|
||||
private final class CloseInInActiveAndUnregisteredChannelHandler: ChannelInboundHandler {
|
||||
typealias InboundIn = Never
|
||||
let alreadyClosedInChannelInactive = Atomic<Bool>(value: false)
|
||||
let alreadyClosedInChannelUnregistered = Atomic<Bool>(value: false)
|
||||
let alreadyClosedInChannelInactive = NIOAtomic<Bool>.makeAtomic(value: false)
|
||||
let alreadyClosedInChannelUnregistered = NIOAtomic<Bool>.makeAtomic(value: false)
|
||||
let channelUnregisteredPromise: EventLoopPromise<Void>
|
||||
let channelInactivePromise: EventLoopPromise<Void>
|
||||
|
||||
|
@ -723,8 +723,8 @@ class EchoServerClientTest : XCTestCase {
|
|||
defer {
|
||||
XCTAssertNoThrow(try group.syncShutdownGracefully())
|
||||
}
|
||||
let acceptedRemotePort: Atomic<Int> = Atomic(value: -1)
|
||||
let acceptedLocalPort: Atomic<Int> = Atomic(value: -2)
|
||||
let acceptedRemotePort: NIOAtomic<Int> = .makeAtomic(value: -1)
|
||||
let acceptedLocalPort: NIOAtomic<Int> = .makeAtomic(value: -2)
|
||||
let sem = DispatchSemaphore(value: 0)
|
||||
|
||||
let serverChannel: Channel
|
||||
|
|
|
@ -73,7 +73,7 @@ public final class EventLoopTest : XCTestCase {
|
|||
defer {
|
||||
XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully())
|
||||
}
|
||||
let ran = Atomic<Bool>(value: false)
|
||||
let ran = NIOAtomic<Bool>.makeAtomic(value: false)
|
||||
let scheduled = eventLoopGroup.next().scheduleTask(in: .seconds(2)) {
|
||||
ran.store(true)
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ public final class EventLoopTest : XCTestCase {
|
|||
}
|
||||
|
||||
let expect = expectation(description: "Is cancelling RepatedTask")
|
||||
let counter = Atomic<Int>(value: 0)
|
||||
let counter = NIOAtomic<Int>.makeAtomic(value: 0)
|
||||
let loop = eventLoopGroup.next()
|
||||
loop.scheduleRepeatedTask(initialDelay: initialDelay, delay: delay) { repeatedTask -> Void in
|
||||
XCTAssertTrue(loop.inEventLoop)
|
||||
|
@ -592,8 +592,8 @@ public final class EventLoopTest : XCTestCase {
|
|||
class AssertHandler: ChannelInboundHandler {
|
||||
typealias InboundIn = Any
|
||||
|
||||
let groupIsShutdown = Atomic(value: false)
|
||||
let removed = Atomic(value: false)
|
||||
let groupIsShutdown = NIOAtomic.makeAtomic(value: false)
|
||||
let removed = NIOAtomic.makeAtomic(value: false)
|
||||
|
||||
public func handlerRemoved(context: ChannelHandlerContext) {
|
||||
XCTAssertFalse(groupIsShutdown.load())
|
||||
|
@ -614,7 +614,7 @@ public final class EventLoopTest : XCTestCase {
|
|||
channel.connect(to: serverSocket.localAddress!)
|
||||
}
|
||||
}.wait() as Void)
|
||||
let closeFutureFulfilledEventually = Atomic<Bool>(value: false)
|
||||
let closeFutureFulfilledEventually = NIOAtomic<Bool>.makeAtomic(value: false)
|
||||
XCTAssertFalse(channel.closeFuture.isFulfilled)
|
||||
channel.closeFuture.whenSuccess {
|
||||
XCTAssertTrue(closeFutureFulfilledEventually.compareAndExchange(expected: false, desired: true))
|
||||
|
|
|
@ -391,7 +391,7 @@ class SelectorTest: XCTestCase {
|
|||
protocol: 0,
|
||||
socketVector: &socketFDs))
|
||||
|
||||
let numberFires = Atomic<Int>(value: 0)
|
||||
let numberFires = NIOAtomic<Int>.makeAtomic(value: 0)
|
||||
let el = group.next() as! SelectableEventLoop
|
||||
let channelHasBeenClosedPromise = el.makePromise(of: Void.self)
|
||||
let channel = try SocketChannel(socket: FakeSocket(hasBeenClosedPromise: channelHasBeenClosedPromise,
|
||||
|
|
|
@ -51,7 +51,7 @@ public final class SocketChannelTest : XCTestCase {
|
|||
|
||||
// Ensure we can dispatch two concurrent set option's on each others
|
||||
// event loops.
|
||||
let condition = Atomic<Int>(value: 0)
|
||||
let condition = NIOAtomic<Int>.makeAtomic(value: 0)
|
||||
let futureA = channelA.eventLoop.submit {
|
||||
_ = condition.add(1)
|
||||
while condition.load() < 2 { }
|
||||
|
@ -684,7 +684,7 @@ public final class SocketChannelTest : XCTestCase {
|
|||
func testServerChannelDoesNotBreakIfAcceptingFailsWithEINVAL() throws {
|
||||
// regression test for https://github.com/apple/swift-nio/issues/1030
|
||||
class HandsOutMoodySocketsServerSocket: ServerSocket {
|
||||
let shouldAcceptsFail: Atomic<Bool> = .init(value: true)
|
||||
let shouldAcceptsFail: NIOAtomic<Bool> = .makeAtomic(value: true)
|
||||
override func accept(setNonBlocking: Bool = false) throws -> Socket? {
|
||||
XCTAssertTrue(setNonBlocking)
|
||||
if self.shouldAcceptsFail.load() {
|
||||
|
|
|
@ -18,9 +18,9 @@ services:
|
|||
test:
|
||||
image: swift-nio:16.04-5.1
|
||||
environment:
|
||||
- MAX_ALLOCS_ALLOWED_1000_reqs_1_conn=30550
|
||||
- MAX_ALLOCS_ALLOWED_1_reqs_1000_conn=533050
|
||||
- MAX_ALLOCS_ALLOWED_ping_pong_1000_reqs_1_conn=4450
|
||||
- MAX_ALLOCS_ALLOWED_1000_reqs_1_conn=30540
|
||||
- MAX_ALLOCS_ALLOWED_1_reqs_1000_conn=522050
|
||||
- MAX_ALLOCS_ALLOWED_ping_pong_1000_reqs_1_conn=4440
|
||||
- MAX_ALLOCS_ALLOWED_bytebuffer_lots_of_rw=2100
|
||||
- MAX_ALLOCS_ALLOWED_future_lots_of_callbacks=75010
|
||||
- MAX_ALLOCS_ALLOWED_creating_10000_headers=10100
|
||||
|
|
|
@ -18,9 +18,9 @@ services:
|
|||
test:
|
||||
image: swift-nio:18.04-5.0
|
||||
environment:
|
||||
- MAX_ALLOCS_ALLOWED_1000_reqs_1_conn=30970
|
||||
- MAX_ALLOCS_ALLOWED_1_reqs_1000_conn=994050
|
||||
- MAX_ALLOCS_ALLOWED_ping_pong_1000_reqs_1_conn=4480
|
||||
- MAX_ALLOCS_ALLOWED_1000_reqs_1_conn=30990
|
||||
- MAX_ALLOCS_ALLOWED_1_reqs_1000_conn=1005050
|
||||
- MAX_ALLOCS_ALLOWED_ping_pong_1000_reqs_1_conn=4500
|
||||
- MAX_ALLOCS_ALLOWED_bytebuffer_lots_of_rw=2100
|
||||
- MAX_ALLOCS_ALLOWED_future_lots_of_callbacks=75010
|
||||
- MAX_ALLOCS_ALLOWED_scheduling_10000_executions=20150
|
||||
|
|
Loading…
Reference in New Issue