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:
Jake 2019-11-28 01:45:05 -06:00 committed by Cory Benfield
parent abe5219b71
commit 3c879ebbaf
19 changed files with 888 additions and 49 deletions

View File

@ -2,7 +2,7 @@
// //
// This source file is part of the SwiftNIO open source project // 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 // Licensed under Apache License v2.0
// //
// See LICENSE.txt for license information // 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_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); 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); 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);

View File

@ -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
)

View File

@ -34,7 +34,7 @@ private struct SocketChannelLifecycleManager {
// MARK: properties // MARK: properties
private let eventLoop: EventLoop private let eventLoop: EventLoop
// this is queried from the Channel, ie. must be thread-safe // 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 // these are only to be accessed on the EventLoop
// have we seen the `.readEOF` notification // have we seen the `.readEOF` notification
@ -57,7 +57,7 @@ private struct SocketChannelLifecycleManager {
// MARK: API // MARK: API
// isActiveAtomic needs to be injected as it's accessed from arbitrary threads and `SocketChannelLifecycleManager` is usually held mutable // 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.eventLoop = eventLoop
self.isActiveAtomic = isActiveAtomic self.isActiveAtomic = isActiveAtomic
} }
@ -213,7 +213,7 @@ class BaseSocketChannel<SocketType: BaseSocketProtocol>: SelectableChannel, Chan
internal let selectableEventLoop: SelectableEventLoop internal let selectableEventLoop: SelectableEventLoop
private let addressesCached: AtomicBox<Box<(local:SocketAddress?, remote:SocketAddress?)>> = AtomicBox(value: Box((local: nil, remote: nil))) private let addressesCached: AtomicBox<Box<(local:SocketAddress?, remote:SocketAddress?)>> = AtomicBox(value: Box((local: nil, remote: nil)))
private let bufferAllocatorCached: AtomicBox<Box<ByteBufferAllocator>> 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 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 // just a thread-safe way of having something to print about the socket from any thread
internal let socketDescription: String internal let socketDescription: String

View File

@ -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. /// 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 typealias ThreadInitializer = (NIOThread) -> Void
@ -1156,7 +1156,7 @@ public final class MultiThreadedEventLoopGroup: EventLoopGroup {
private static let threadSpecificEventLoop = ThreadSpecificVariable<SelectableEventLoop>() 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 eventLoops: [SelectableEventLoop]
private let shutdownLock: Lock = Lock() private let shutdownLock: Lock = Lock()
private var runState: RunState = .running private var runState: RunState = .running

View File

@ -360,7 +360,7 @@ final class PendingDatagramWritesManager: PendingWritesManager {
private var state = PendingDatagramWritesState() private var state = PendingDatagramWritesState()
internal var waterMark: ChannelOptions.Types.WriteBufferWaterMark = ChannelOptions.Types.WriteBufferWaterMark(low: 32 * 1024, high: 64 * 1024) 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 internal var writeSpinCount: UInt = 16
private(set) var isOpen = true private(set) var isOpen = true

View File

@ -277,7 +277,7 @@ final class PendingStreamWritesManager: PendingWritesManager {
private var storageRefs: UnsafeMutableBufferPointer<Unmanaged<AnyObject>> private var storageRefs: UnsafeMutableBufferPointer<Unmanaged<AnyObject>>
internal var waterMark: ChannelOptions.Types.WriteBufferWaterMark = ChannelOptions.Types.WriteBufferWaterMark(low: 32 * 1024, high: 64 * 1024) 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 internal var writeSpinCount: UInt = 16
@ -451,7 +451,7 @@ internal protocol PendingWritesManager {
var isFlushPending: Bool { get } var isFlushPending: Bool { get }
var writeSpinCount: UInt { get } var writeSpinCount: UInt { get }
var currentBestWriteMechanism: WriteMechanism { get } var currentBestWriteMechanism: WriteMechanism { get }
var channelWritabilityFlag: Atomic<Bool> { get } var channelWritabilityFlag: NIOAtomic<Bool> { get }
} }
extension PendingWritesManager { extension PendingWritesManager {

View File

@ -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)
}
}
}

View File

@ -153,6 +153,7 @@ public struct UnsafeEmbeddedAtomic<T: AtomicPrimitive> {
/// By necessity, all atomic values are references: after all, it makes no /// 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 /// sense to talk about managing an atomic value when each time it's modified
/// the thread that modified it gets a local copy! /// the thread that modified it gets a local copy!
@available(*, deprecated, message:"please use NIOAtomic instead")
public final class Atomic<T: AtomicPrimitive> { public final class Atomic<T: AtomicPrimitive> {
@usableFromInline @usableFromInline
internal let embedded: UnsafeEmbeddedAtomic<T> 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. /// It behaves very much like `Atomic<T>` but for objects, maintaining the correct retain counts.
public final class AtomicBox<T: AnyObject> { public final class AtomicBox<T: AnyObject> {
private let storage: Atomic<UInt> private let storage: NIOAtomic<UInt>
public init(value: T) { public init(value: T) {
let ptr = Unmanaged<T>.passRetained(value) let ptr = Unmanaged<T>.passRetained(value)
self.storage = Atomic(value: UInt(bitPattern: ptr.toOpaque())) self.storage = NIOAtomic.makeAtomic(value: UInt(bitPattern: ptr.toOpaque()))
} }
deinit { deinit {

View File

@ -24,23 +24,23 @@ import NIOConcurrencyHelpers
/// - note: Contrary to most `ChannelHandler`s, all of `EventCounterHandler`'s API is thread-safe meaning that you can /// - 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. /// query the events received from any thread.
public final class EventCounterHandler { public final class EventCounterHandler {
private let _channelRegisteredCalls = Atomic<Int>(value: 0) private let _channelRegisteredCalls = NIOAtomic<Int>.makeAtomic(value: 0)
private let _channelUnregisteredCalls = Atomic<Int>(value: 0) private let _channelUnregisteredCalls = NIOAtomic<Int>.makeAtomic(value: 0)
private let _channelActiveCalls = Atomic<Int>(value: 0) private let _channelActiveCalls = NIOAtomic<Int>.makeAtomic(value: 0)
private let _channelInactiveCalls = Atomic<Int>(value: 0) private let _channelInactiveCalls = NIOAtomic<Int>.makeAtomic(value: 0)
private let _channelReadCalls = Atomic<Int>(value: 0) private let _channelReadCalls = NIOAtomic<Int>.makeAtomic(value: 0)
private let _channelReadCompleteCalls = Atomic<Int>(value: 0) private let _channelReadCompleteCalls = NIOAtomic<Int>.makeAtomic(value: 0)
private let _channelWritabilityChangedCalls = Atomic<Int>(value: 0) private let _channelWritabilityChangedCalls = NIOAtomic<Int>.makeAtomic(value: 0)
private let _userInboundEventTriggeredCalls = Atomic<Int>(value: 0) private let _userInboundEventTriggeredCalls = NIOAtomic<Int>.makeAtomic(value: 0)
private let _errorCaughtCalls = Atomic<Int>(value: 0) private let _errorCaughtCalls = NIOAtomic<Int>.makeAtomic(value: 0)
private let _registerCalls = Atomic<Int>(value: 0) private let _registerCalls = NIOAtomic<Int>.makeAtomic(value: 0)
private let _bindCalls = Atomic<Int>(value: 0) private let _bindCalls = NIOAtomic<Int>.makeAtomic(value: 0)
private let _connectCalls = Atomic<Int>(value: 0) private let _connectCalls = NIOAtomic<Int>.makeAtomic(value: 0)
private let _writeCalls = Atomic<Int>(value: 0) private let _writeCalls = NIOAtomic<Int>.makeAtomic(value: 0)
private let _flushCalls = Atomic<Int>(value: 0) private let _flushCalls = NIOAtomic<Int>.makeAtomic(value: 0)
private let _readCalls = Atomic<Int>(value: 0) private let _readCalls = NIOAtomic<Int>.makeAtomic(value: 0)
private let _closeCalls = Atomic<Int>(value: 0) private let _closeCalls = NIOAtomic<Int>.makeAtomic(value: 0)
private let _triggerUserOutboundEventCalls = Atomic<Int>(value: 0) private let _triggerUserOutboundEventCalls = NIOAtomic<Int>.makeAtomic(value: 0)
public init() {} public init() {}
} }

View File

@ -35,6 +35,14 @@ extension NIOConcurrencyHelpersTests {
("testAddSub", testAddSub), ("testAddSub", testAddSub),
("testExchange", testExchange), ("testExchange", testExchange),
("testLoadStore", testLoadStore), ("testLoadStore", testLoadStore),
("testLargeContendedNIOAtomicSum", testLargeContendedNIOAtomicSum),
("testCompareAndExchangeBoolNIOAtomic", testCompareAndExchangeBoolNIOAtomic),
("testAllOperationsBoolNIOAtomic", testAllOperationsBoolNIOAtomic),
("testCompareAndExchangeUIntsNIOAtomic", testCompareAndExchangeUIntsNIOAtomic),
("testCompareAndExchangeIntsNIOAtomic", testCompareAndExchangeIntsNIOAtomic),
("testAddSubNIOAtomic", testAddSubNIOAtomic),
("testExchangeNIOAtomic", testExchangeNIOAtomic),
("testLoadStoreNIOAtomic", testLoadStoreNIOAtomic),
("testLockMutualExclusion", testLockMutualExclusion), ("testLockMutualExclusion", testLockMutualExclusion),
("testWithLockMutualExclusion", testWithLockMutualExclusion), ("testWithLockMutualExclusion", testWithLockMutualExclusion),
("testConditionLockMutualExclusion", testConditionLockMutualExclusion), ("testConditionLockMutualExclusion", testConditionLockMutualExclusion),

View File

@ -25,6 +25,7 @@ class NIOConcurrencyHelpersTests: XCTestCase {
return n*(n+1)/2 return n*(n+1)/2
} }
@available(*, deprecated, message: "deprecated because it tests deprecated functionality")
func testLargeContendedAtomicSum() { func testLargeContendedAtomicSum() {
let noAsyncs: UInt64 = 64 let noAsyncs: UInt64 = 64
let noCounts: UInt64 = 200_000 let noCounts: UInt64 = 200_000
@ -43,6 +44,7 @@ class NIOConcurrencyHelpersTests: XCTestCase {
XCTAssertEqual(sumOfIntegers(until: noAsyncs) * noCounts, ai.load()) XCTAssertEqual(sumOfIntegers(until: noAsyncs) * noCounts, ai.load())
} }
@available(*, deprecated, message: "deprecated because it tests deprecated functionality")
func testCompareAndExchangeBool() { func testCompareAndExchangeBool() {
let ab = Atomic<Bool>(value: true) let ab = Atomic<Bool>(value: true)
@ -56,6 +58,7 @@ class NIOConcurrencyHelpersTests: XCTestCase {
XCTAssertTrue(ab.compareAndExchange(expected: false, desired: true)) XCTAssertTrue(ab.compareAndExchange(expected: false, desired: true))
} }
@available(*, deprecated, message: "deprecated because it tests deprecated functionality")
func testAllOperationsBool() { func testAllOperationsBool() {
let ab = Atomic<Bool>(value: false) let ab = Atomic<Bool>(value: false)
XCTAssertEqual(false, ab.load()) XCTAssertEqual(false, ab.load())
@ -72,6 +75,7 @@ class NIOConcurrencyHelpersTests: XCTestCase {
XCTAssertFalse(ab.compareAndExchange(expected: false, desired: true)) XCTAssertFalse(ab.compareAndExchange(expected: false, desired: true))
} }
@available(*, deprecated, message: "deprecated because it tests deprecated functionality")
func testCompareAndExchangeUInts() { func testCompareAndExchangeUInts() {
func testFor<T: AtomicPrimitive & FixedWidthInteger & UnsignedInteger>(_ value: T.Type) { func testFor<T: AtomicPrimitive & FixedWidthInteger & UnsignedInteger>(_ value: T.Type) {
let zero: T = 0 let zero: T = 0
@ -102,6 +106,7 @@ class NIOConcurrencyHelpersTests: XCTestCase {
testFor(UInt.self) testFor(UInt.self)
} }
@available(*, deprecated, message: "deprecated because it tests deprecated functionality")
func testCompareAndExchangeInts() { func testCompareAndExchangeInts() {
func testFor<T: AtomicPrimitive & FixedWidthInteger & SignedInteger>(_ value: T.Type) { func testFor<T: AtomicPrimitive & FixedWidthInteger & SignedInteger>(_ value: T.Type) {
let zero: T = 0 let zero: T = 0
@ -133,6 +138,7 @@ class NIOConcurrencyHelpersTests: XCTestCase {
testFor(Int.self) testFor(Int.self)
} }
@available(*, deprecated, message: "deprecated because it tests deprecated functionality")
func testAddSub() { func testAddSub() {
func testFor<T: AtomicPrimitive & FixedWidthInteger>(_ value: T.Type) { func testFor<T: AtomicPrimitive & FixedWidthInteger>(_ value: T.Type) {
let zero: T = 0 let zero: T = 0
@ -164,6 +170,7 @@ class NIOConcurrencyHelpersTests: XCTestCase {
testFor(UInt.self) testFor(UInt.self)
} }
@available(*, deprecated, message: "deprecated because it tests deprecated functionality")
func testExchange() { func testExchange() {
func testFor<T: AtomicPrimitive & FixedWidthInteger>(_ value: T.Type) { func testFor<T: AtomicPrimitive & FixedWidthInteger>(_ value: T.Type) {
let zero: T = 0 let zero: T = 0
@ -195,6 +202,7 @@ class NIOConcurrencyHelpersTests: XCTestCase {
testFor(UInt.self) testFor(UInt.self)
} }
@available(*, deprecated, message: "deprecated because it tests deprecated functionality")
func testLoadStore() { func testLoadStore() {
func testFor<T: AtomicPrimitive & FixedWidthInteger>(_ value: T.Type) { func testFor<T: AtomicPrimitive & FixedWidthInteger>(_ value: T.Type) {
let zero: T = 0 let zero: T = 0
@ -220,6 +228,202 @@ class NIOConcurrencyHelpersTests: XCTestCase {
testFor(UInt.self) 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() { func testLockMutualExclusion() {
let l = Lock() let l = Lock()

View File

@ -200,7 +200,7 @@ public final class AcceptBackoffHandlerTest: XCTestCase {
let readCountHandler = ReadCountHandler() 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 let serverChannel = try setupChannel(group: group, readCountHandler: readCountHandler, backoffProvider: { err in
if backoffProviderCalled.add(1) == 0 { if backoffProviderCalled.add(1) == 0 {
return .seconds(1) return .seconds(1)

View File

@ -163,8 +163,8 @@ class ChannelPipelineTest: XCTestCase {
} }
private final class DummyHandler: ChannelHandler { private final class DummyHandler: ChannelHandler {
let handlerAddedCalled = Atomic<Bool>(value: false) let handlerAddedCalled = NIOAtomic<Bool>.makeAtomic(value: false)
let handlerRemovedCalled = Atomic<Bool>(value: false) let handlerRemovedCalled = NIOAtomic<Bool>.makeAtomic(value: false)
public func handlerAdded(context: ChannelHandlerContext) { public func handlerAdded(context: ChannelHandlerContext) {
handlerAddedCalled.store(true) handlerAddedCalled.store(true)

View File

@ -313,8 +313,8 @@ class EchoServerClientTest : XCTestCase {
private final class CloseInInActiveAndUnregisteredChannelHandler: ChannelInboundHandler { private final class CloseInInActiveAndUnregisteredChannelHandler: ChannelInboundHandler {
typealias InboundIn = Never typealias InboundIn = Never
let alreadyClosedInChannelInactive = Atomic<Bool>(value: false) let alreadyClosedInChannelInactive = NIOAtomic<Bool>.makeAtomic(value: false)
let alreadyClosedInChannelUnregistered = Atomic<Bool>(value: false) let alreadyClosedInChannelUnregistered = NIOAtomic<Bool>.makeAtomic(value: false)
let channelUnregisteredPromise: EventLoopPromise<Void> let channelUnregisteredPromise: EventLoopPromise<Void>
let channelInactivePromise: EventLoopPromise<Void> let channelInactivePromise: EventLoopPromise<Void>
@ -723,8 +723,8 @@ class EchoServerClientTest : XCTestCase {
defer { defer {
XCTAssertNoThrow(try group.syncShutdownGracefully()) XCTAssertNoThrow(try group.syncShutdownGracefully())
} }
let acceptedRemotePort: Atomic<Int> = Atomic(value: -1) let acceptedRemotePort: NIOAtomic<Int> = .makeAtomic(value: -1)
let acceptedLocalPort: Atomic<Int> = Atomic(value: -2) let acceptedLocalPort: NIOAtomic<Int> = .makeAtomic(value: -2)
let sem = DispatchSemaphore(value: 0) let sem = DispatchSemaphore(value: 0)
let serverChannel: Channel let serverChannel: Channel

View File

@ -73,7 +73,7 @@ public final class EventLoopTest : XCTestCase {
defer { defer {
XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) 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)) { let scheduled = eventLoopGroup.next().scheduleTask(in: .seconds(2)) {
ran.store(true) ran.store(true)
} }
@ -102,7 +102,7 @@ public final class EventLoopTest : XCTestCase {
} }
let expect = expectation(description: "Is cancelling RepatedTask") let expect = expectation(description: "Is cancelling RepatedTask")
let counter = Atomic<Int>(value: 0) let counter = NIOAtomic<Int>.makeAtomic(value: 0)
let loop = eventLoopGroup.next() let loop = eventLoopGroup.next()
loop.scheduleRepeatedTask(initialDelay: initialDelay, delay: delay) { repeatedTask -> Void in loop.scheduleRepeatedTask(initialDelay: initialDelay, delay: delay) { repeatedTask -> Void in
XCTAssertTrue(loop.inEventLoop) XCTAssertTrue(loop.inEventLoop)
@ -592,8 +592,8 @@ public final class EventLoopTest : XCTestCase {
class AssertHandler: ChannelInboundHandler { class AssertHandler: ChannelInboundHandler {
typealias InboundIn = Any typealias InboundIn = Any
let groupIsShutdown = Atomic(value: false) let groupIsShutdown = NIOAtomic.makeAtomic(value: false)
let removed = Atomic(value: false) let removed = NIOAtomic.makeAtomic(value: false)
public func handlerRemoved(context: ChannelHandlerContext) { public func handlerRemoved(context: ChannelHandlerContext) {
XCTAssertFalse(groupIsShutdown.load()) XCTAssertFalse(groupIsShutdown.load())
@ -614,7 +614,7 @@ public final class EventLoopTest : XCTestCase {
channel.connect(to: serverSocket.localAddress!) channel.connect(to: serverSocket.localAddress!)
} }
}.wait() as Void) }.wait() as Void)
let closeFutureFulfilledEventually = Atomic<Bool>(value: false) let closeFutureFulfilledEventually = NIOAtomic<Bool>.makeAtomic(value: false)
XCTAssertFalse(channel.closeFuture.isFulfilled) XCTAssertFalse(channel.closeFuture.isFulfilled)
channel.closeFuture.whenSuccess { channel.closeFuture.whenSuccess {
XCTAssertTrue(closeFutureFulfilledEventually.compareAndExchange(expected: false, desired: true)) XCTAssertTrue(closeFutureFulfilledEventually.compareAndExchange(expected: false, desired: true))

View File

@ -391,7 +391,7 @@ class SelectorTest: XCTestCase {
protocol: 0, protocol: 0,
socketVector: &socketFDs)) socketVector: &socketFDs))
let numberFires = Atomic<Int>(value: 0) let numberFires = NIOAtomic<Int>.makeAtomic(value: 0)
let el = group.next() as! SelectableEventLoop let el = group.next() as! SelectableEventLoop
let channelHasBeenClosedPromise = el.makePromise(of: Void.self) let channelHasBeenClosedPromise = el.makePromise(of: Void.self)
let channel = try SocketChannel(socket: FakeSocket(hasBeenClosedPromise: channelHasBeenClosedPromise, let channel = try SocketChannel(socket: FakeSocket(hasBeenClosedPromise: channelHasBeenClosedPromise,

View File

@ -51,7 +51,7 @@ public final class SocketChannelTest : XCTestCase {
// Ensure we can dispatch two concurrent set option's on each others // Ensure we can dispatch two concurrent set option's on each others
// event loops. // event loops.
let condition = Atomic<Int>(value: 0) let condition = NIOAtomic<Int>.makeAtomic(value: 0)
let futureA = channelA.eventLoop.submit { let futureA = channelA.eventLoop.submit {
_ = condition.add(1) _ = condition.add(1)
while condition.load() < 2 { } while condition.load() < 2 { }
@ -684,7 +684,7 @@ public final class SocketChannelTest : XCTestCase {
func testServerChannelDoesNotBreakIfAcceptingFailsWithEINVAL() throws { func testServerChannelDoesNotBreakIfAcceptingFailsWithEINVAL() throws {
// regression test for https://github.com/apple/swift-nio/issues/1030 // regression test for https://github.com/apple/swift-nio/issues/1030
class HandsOutMoodySocketsServerSocket: ServerSocket { 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? { override func accept(setNonBlocking: Bool = false) throws -> Socket? {
XCTAssertTrue(setNonBlocking) XCTAssertTrue(setNonBlocking)
if self.shouldAcceptsFail.load() { if self.shouldAcceptsFail.load() {

View File

@ -18,9 +18,9 @@ services:
test: test:
image: swift-nio:16.04-5.1 image: swift-nio:16.04-5.1
environment: environment:
- MAX_ALLOCS_ALLOWED_1000_reqs_1_conn=30550 - MAX_ALLOCS_ALLOWED_1000_reqs_1_conn=30540
- MAX_ALLOCS_ALLOWED_1_reqs_1000_conn=533050 - MAX_ALLOCS_ALLOWED_1_reqs_1000_conn=522050
- MAX_ALLOCS_ALLOWED_ping_pong_1000_reqs_1_conn=4450 - MAX_ALLOCS_ALLOWED_ping_pong_1000_reqs_1_conn=4440
- MAX_ALLOCS_ALLOWED_bytebuffer_lots_of_rw=2100 - MAX_ALLOCS_ALLOWED_bytebuffer_lots_of_rw=2100
- MAX_ALLOCS_ALLOWED_future_lots_of_callbacks=75010 - MAX_ALLOCS_ALLOWED_future_lots_of_callbacks=75010
- MAX_ALLOCS_ALLOWED_creating_10000_headers=10100 - MAX_ALLOCS_ALLOWED_creating_10000_headers=10100

View File

@ -18,9 +18,9 @@ services:
test: test:
image: swift-nio:18.04-5.0 image: swift-nio:18.04-5.0
environment: environment:
- MAX_ALLOCS_ALLOWED_1000_reqs_1_conn=30970 - MAX_ALLOCS_ALLOWED_1000_reqs_1_conn=30990
- MAX_ALLOCS_ALLOWED_1_reqs_1000_conn=994050 - MAX_ALLOCS_ALLOWED_1_reqs_1000_conn=1005050
- MAX_ALLOCS_ALLOWED_ping_pong_1000_reqs_1_conn=4480 - MAX_ALLOCS_ALLOWED_ping_pong_1000_reqs_1_conn=4500
- MAX_ALLOCS_ALLOWED_bytebuffer_lots_of_rw=2100 - MAX_ALLOCS_ALLOWED_bytebuffer_lots_of_rw=2100
- MAX_ALLOCS_ALLOWED_future_lots_of_callbacks=75010 - MAX_ALLOCS_ALLOWED_future_lots_of_callbacks=75010
- MAX_ALLOCS_ALLOWED_scheduling_10000_executions=20150 - MAX_ALLOCS_ALLOWED_scheduling_10000_executions=20150