merge ConcurrencyHelpers
This commit is contained in:
parent
33fe401322
commit
06f9b1d63b
|
@ -0,0 +1,234 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct catmc_atomic__Bool;
|
||||
struct catmc_atomic__Bool * _Nonnull catmc_atomic__Bool_create(bool value);
|
||||
void catmc_atomic__Bool_destroy(struct catmc_atomic__Bool * _Nonnull atomic);
|
||||
bool catmc_atomic__Bool_compare_and_exchange(struct catmc_atomic__Bool * _Nonnull atomic, bool expected, bool desired);
|
||||
bool catmc_atomic__Bool_add(struct catmc_atomic__Bool * _Nonnull atomic, bool value);
|
||||
bool catmc_atomic__Bool_sub(struct catmc_atomic__Bool * _Nonnull atomic, bool value);
|
||||
bool catmc_atomic__Bool_exchange(struct catmc_atomic__Bool * _Nonnull atomic, bool value);
|
||||
bool catmc_atomic__Bool_load(struct catmc_atomic__Bool * _Nonnull atomic);
|
||||
void catmc_atomic__Bool_store(struct catmc_atomic__Bool * _Nonnull atomic, bool value);
|
||||
struct catmc_atomic_char;
|
||||
struct catmc_atomic_char * _Nonnull catmc_atomic_char_create(char value);
|
||||
void catmc_atomic_char_destroy(struct catmc_atomic_char * _Nonnull atomic);
|
||||
bool catmc_atomic_char_compare_and_exchange(struct catmc_atomic_char * _Nonnull atomic, char expected, char desired);
|
||||
char catmc_atomic_char_add(struct catmc_atomic_char * _Nonnull atomic, char value);
|
||||
char catmc_atomic_char_sub(struct catmc_atomic_char * _Nonnull atomic, char value);
|
||||
char catmc_atomic_char_exchange(struct catmc_atomic_char * _Nonnull atomic, char value);
|
||||
char catmc_atomic_char_load(struct catmc_atomic_char * _Nonnull atomic);
|
||||
void catmc_atomic_char_store(struct catmc_atomic_char * _Nonnull atomic, char value);
|
||||
struct catmc_atomic_short;
|
||||
struct catmc_atomic_short * _Nonnull catmc_atomic_short_create(short value);
|
||||
void catmc_atomic_short_destroy(struct catmc_atomic_short * _Nonnull atomic);
|
||||
bool catmc_atomic_short_compare_and_exchange(struct catmc_atomic_short * _Nonnull atomic, short expected, short desired);
|
||||
short catmc_atomic_short_add(struct catmc_atomic_short * _Nonnull atomic, short value);
|
||||
short catmc_atomic_short_sub(struct catmc_atomic_short * _Nonnull atomic, short value);
|
||||
short catmc_atomic_short_exchange(struct catmc_atomic_short * _Nonnull atomic, short value);
|
||||
short catmc_atomic_short_load(struct catmc_atomic_short * _Nonnull atomic);
|
||||
void catmc_atomic_short_store(struct catmc_atomic_short * _Nonnull atomic, short value);
|
||||
struct catmc_atomic_int;
|
||||
struct catmc_atomic_int * _Nonnull catmc_atomic_int_create(int value);
|
||||
void catmc_atomic_int_destroy(struct catmc_atomic_int * _Nonnull atomic);
|
||||
bool catmc_atomic_int_compare_and_exchange(struct catmc_atomic_int * _Nonnull atomic, int expected, int desired);
|
||||
int catmc_atomic_int_add(struct catmc_atomic_int * _Nonnull atomic, int value);
|
||||
int catmc_atomic_int_sub(struct catmc_atomic_int * _Nonnull atomic, int value);
|
||||
int catmc_atomic_int_exchange(struct catmc_atomic_int * _Nonnull atomic, int value);
|
||||
int catmc_atomic_int_load(struct catmc_atomic_int * _Nonnull atomic);
|
||||
void catmc_atomic_int_store(struct catmc_atomic_int * _Nonnull atomic, int value);
|
||||
struct catmc_atomic_long;
|
||||
struct catmc_atomic_long * _Nonnull catmc_atomic_long_create(long value);
|
||||
void catmc_atomic_long_destroy(struct catmc_atomic_long * _Nonnull atomic);
|
||||
bool catmc_atomic_long_compare_and_exchange(struct catmc_atomic_long * _Nonnull atomic, long expected, long desired);
|
||||
long catmc_atomic_long_add(struct catmc_atomic_long * _Nonnull atomic, long value);
|
||||
long catmc_atomic_long_sub(struct catmc_atomic_long * _Nonnull atomic, long value);
|
||||
long catmc_atomic_long_exchange(struct catmc_atomic_long * _Nonnull atomic, long value);
|
||||
long catmc_atomic_long_load(struct catmc_atomic_long * _Nonnull atomic);
|
||||
void catmc_atomic_long_store(struct catmc_atomic_long * _Nonnull atomic, long value);
|
||||
struct catmc_atomic_long_long;
|
||||
struct catmc_atomic_long_long * _Nonnull catmc_atomic_long_long_create(long long value);
|
||||
void catmc_atomic_long_long_destroy(struct catmc_atomic_long_long * _Nonnull atomic);
|
||||
bool catmc_atomic_long_long_compare_and_exchange(struct catmc_atomic_long_long * _Nonnull atomic, long long expected, long long desired);
|
||||
long long catmc_atomic_long_long_add(struct catmc_atomic_long_long * _Nonnull atomic, long long value);
|
||||
long long catmc_atomic_long_long_sub(struct catmc_atomic_long_long * _Nonnull atomic, long long value);
|
||||
long long catmc_atomic_long_long_exchange(struct catmc_atomic_long_long * _Nonnull atomic, long long value);
|
||||
long long catmc_atomic_long_long_load(struct catmc_atomic_long_long * _Nonnull atomic);
|
||||
void catmc_atomic_long_long_store(struct catmc_atomic_long_long * _Nonnull atomic, long long value);
|
||||
struct catmc_atomic_signed_char;
|
||||
struct catmc_atomic_signed_char * _Nonnull catmc_atomic_signed_char_create(signed char value);
|
||||
void catmc_atomic_signed_char_destroy(struct catmc_atomic_signed_char * _Nonnull atomic);
|
||||
bool catmc_atomic_signed_char_compare_and_exchange(struct catmc_atomic_signed_char * _Nonnull atomic, signed char expected, signed char desired);
|
||||
signed char catmc_atomic_signed_char_add(struct catmc_atomic_signed_char * _Nonnull atomic, signed char value);
|
||||
signed char catmc_atomic_signed_char_sub(struct catmc_atomic_signed_char * _Nonnull atomic, signed char value);
|
||||
signed char catmc_atomic_signed_char_exchange(struct catmc_atomic_signed_char * _Nonnull atomic, signed char value);
|
||||
signed char catmc_atomic_signed_char_load(struct catmc_atomic_signed_char * _Nonnull atomic);
|
||||
void catmc_atomic_signed_char_store(struct catmc_atomic_signed_char * _Nonnull atomic, signed char value);
|
||||
struct catmc_atomic_signed_short;
|
||||
struct catmc_atomic_signed_short * _Nonnull catmc_atomic_signed_short_create(signed short value);
|
||||
void catmc_atomic_signed_short_destroy(struct catmc_atomic_signed_short * _Nonnull atomic);
|
||||
bool catmc_atomic_signed_short_compare_and_exchange(struct catmc_atomic_signed_short * _Nonnull atomic, signed short expected, signed short desired);
|
||||
signed short catmc_atomic_signed_short_add(struct catmc_atomic_signed_short * _Nonnull atomic, signed short value);
|
||||
signed short catmc_atomic_signed_short_sub(struct catmc_atomic_signed_short * _Nonnull atomic, signed short value);
|
||||
signed short catmc_atomic_signed_short_exchange(struct catmc_atomic_signed_short * _Nonnull atomic, signed short value);
|
||||
signed short catmc_atomic_signed_short_load(struct catmc_atomic_signed_short * _Nonnull atomic);
|
||||
void catmc_atomic_signed_short_store(struct catmc_atomic_signed_short * _Nonnull atomic, signed short value);
|
||||
struct catmc_atomic_signed_int;
|
||||
struct catmc_atomic_signed_int * _Nonnull catmc_atomic_signed_int_create(signed int value);
|
||||
void catmc_atomic_signed_int_destroy(struct catmc_atomic_signed_int * _Nonnull atomic);
|
||||
bool catmc_atomic_signed_int_compare_and_exchange(struct catmc_atomic_signed_int * _Nonnull atomic, signed int expected, signed int desired);
|
||||
signed int catmc_atomic_signed_int_add(struct catmc_atomic_signed_int * _Nonnull atomic, signed int value);
|
||||
signed int catmc_atomic_signed_int_sub(struct catmc_atomic_signed_int * _Nonnull atomic, signed int value);
|
||||
signed int catmc_atomic_signed_int_exchange(struct catmc_atomic_signed_int * _Nonnull atomic, signed int value);
|
||||
signed int catmc_atomic_signed_int_load(struct catmc_atomic_signed_int * _Nonnull atomic);
|
||||
void catmc_atomic_signed_int_store(struct catmc_atomic_signed_int * _Nonnull atomic, signed int value);
|
||||
struct catmc_atomic_signed_long;
|
||||
struct catmc_atomic_signed_long * _Nonnull catmc_atomic_signed_long_create(signed long value);
|
||||
void catmc_atomic_signed_long_destroy(struct catmc_atomic_signed_long * _Nonnull atomic);
|
||||
bool catmc_atomic_signed_long_compare_and_exchange(struct catmc_atomic_signed_long * _Nonnull atomic, signed long expected, signed long desired);
|
||||
signed long catmc_atomic_signed_long_add(struct catmc_atomic_signed_long * _Nonnull atomic, signed long value);
|
||||
signed long catmc_atomic_signed_long_sub(struct catmc_atomic_signed_long * _Nonnull atomic, signed long value);
|
||||
signed long catmc_atomic_signed_long_exchange(struct catmc_atomic_signed_long * _Nonnull atomic, signed long value);
|
||||
signed long catmc_atomic_signed_long_load(struct catmc_atomic_signed_long * _Nonnull atomic);
|
||||
void catmc_atomic_signed_long_store(struct catmc_atomic_signed_long * _Nonnull atomic, signed long value);
|
||||
struct catmc_atomic_signed_long_long;
|
||||
struct catmc_atomic_signed_long_long * _Nonnull catmc_atomic_signed_long_long_create(signed long long value);
|
||||
void catmc_atomic_signed_long_long_destroy(struct catmc_atomic_signed_long_long * _Nonnull atomic);
|
||||
bool catmc_atomic_signed_long_long_compare_and_exchange(struct catmc_atomic_signed_long_long * _Nonnull atomic, signed long long expected, signed long long desired);
|
||||
signed long long catmc_atomic_signed_long_long_add(struct catmc_atomic_signed_long_long * _Nonnull atomic, signed long long value);
|
||||
signed long long catmc_atomic_signed_long_long_sub(struct catmc_atomic_signed_long_long * _Nonnull atomic, signed long long value);
|
||||
signed long long catmc_atomic_signed_long_long_exchange(struct catmc_atomic_signed_long_long * _Nonnull atomic, signed long long value);
|
||||
signed long long catmc_atomic_signed_long_long_load(struct catmc_atomic_signed_long_long * _Nonnull atomic);
|
||||
void catmc_atomic_signed_long_long_store(struct catmc_atomic_signed_long_long * _Nonnull atomic, signed long long value);
|
||||
struct catmc_atomic_unsigned_char;
|
||||
struct catmc_atomic_unsigned_char * _Nonnull catmc_atomic_unsigned_char_create(unsigned char value);
|
||||
void catmc_atomic_unsigned_char_destroy(struct catmc_atomic_unsigned_char * _Nonnull atomic);
|
||||
bool catmc_atomic_unsigned_char_compare_and_exchange(struct catmc_atomic_unsigned_char * _Nonnull atomic, unsigned char expected, unsigned char desired);
|
||||
unsigned char catmc_atomic_unsigned_char_add(struct catmc_atomic_unsigned_char * _Nonnull atomic, unsigned char value);
|
||||
unsigned char catmc_atomic_unsigned_char_sub(struct catmc_atomic_unsigned_char * _Nonnull atomic, unsigned char value);
|
||||
unsigned char catmc_atomic_unsigned_char_exchange(struct catmc_atomic_unsigned_char * _Nonnull atomic, unsigned char value);
|
||||
unsigned char catmc_atomic_unsigned_char_load(struct catmc_atomic_unsigned_char * _Nonnull atomic);
|
||||
void catmc_atomic_unsigned_char_store(struct catmc_atomic_unsigned_char * _Nonnull atomic, unsigned char value);
|
||||
struct catmc_atomic_unsigned_short;
|
||||
struct catmc_atomic_unsigned_short * _Nonnull catmc_atomic_unsigned_short_create(unsigned short value);
|
||||
void catmc_atomic_unsigned_short_destroy(struct catmc_atomic_unsigned_short * _Nonnull atomic);
|
||||
bool catmc_atomic_unsigned_short_compare_and_exchange(struct catmc_atomic_unsigned_short * _Nonnull atomic, unsigned short expected, unsigned short desired);
|
||||
unsigned short catmc_atomic_unsigned_short_add(struct catmc_atomic_unsigned_short * _Nonnull atomic, unsigned short value);
|
||||
unsigned short catmc_atomic_unsigned_short_sub(struct catmc_atomic_unsigned_short * _Nonnull atomic, unsigned short value);
|
||||
unsigned short catmc_atomic_unsigned_short_exchange(struct catmc_atomic_unsigned_short * _Nonnull atomic, unsigned short value);
|
||||
unsigned short catmc_atomic_unsigned_short_load(struct catmc_atomic_unsigned_short * _Nonnull atomic);
|
||||
void catmc_atomic_unsigned_short_store(struct catmc_atomic_unsigned_short * _Nonnull atomic, unsigned short value);
|
||||
struct catmc_atomic_unsigned_int;
|
||||
struct catmc_atomic_unsigned_int * _Nonnull catmc_atomic_unsigned_int_create(unsigned int value);
|
||||
void catmc_atomic_unsigned_int_destroy(struct catmc_atomic_unsigned_int * _Nonnull atomic);
|
||||
bool catmc_atomic_unsigned_int_compare_and_exchange(struct catmc_atomic_unsigned_int * _Nonnull atomic, unsigned int expected, unsigned int desired);
|
||||
unsigned int catmc_atomic_unsigned_int_add(struct catmc_atomic_unsigned_int * _Nonnull atomic, unsigned int value);
|
||||
unsigned int catmc_atomic_unsigned_int_sub(struct catmc_atomic_unsigned_int * _Nonnull atomic, unsigned int value);
|
||||
unsigned int catmc_atomic_unsigned_int_exchange(struct catmc_atomic_unsigned_int * _Nonnull atomic, unsigned int value);
|
||||
unsigned int catmc_atomic_unsigned_int_load(struct catmc_atomic_unsigned_int * _Nonnull atomic);
|
||||
void catmc_atomic_unsigned_int_store(struct catmc_atomic_unsigned_int * _Nonnull atomic, unsigned int value);
|
||||
struct catmc_atomic_unsigned_long;
|
||||
struct catmc_atomic_unsigned_long * _Nonnull catmc_atomic_unsigned_long_create(unsigned long value);
|
||||
void catmc_atomic_unsigned_long_destroy(struct catmc_atomic_unsigned_long * _Nonnull atomic);
|
||||
bool catmc_atomic_unsigned_long_compare_and_exchange(struct catmc_atomic_unsigned_long * _Nonnull atomic, unsigned long expected, unsigned long desired);
|
||||
unsigned long catmc_atomic_unsigned_long_add(struct catmc_atomic_unsigned_long * _Nonnull atomic, unsigned long value);
|
||||
unsigned long catmc_atomic_unsigned_long_sub(struct catmc_atomic_unsigned_long * _Nonnull atomic, unsigned long value);
|
||||
unsigned long catmc_atomic_unsigned_long_exchange(struct catmc_atomic_unsigned_long * _Nonnull atomic, unsigned long value);
|
||||
unsigned long catmc_atomic_unsigned_long_load(struct catmc_atomic_unsigned_long * _Nonnull atomic);
|
||||
void catmc_atomic_unsigned_long_store(struct catmc_atomic_unsigned_long * _Nonnull atomic, unsigned long value);
|
||||
struct catmc_atomic_unsigned_long_long;
|
||||
struct catmc_atomic_unsigned_long_long * _Nonnull catmc_atomic_unsigned_long_long_create(unsigned long long value);
|
||||
void catmc_atomic_unsigned_long_long_destroy(struct catmc_atomic_unsigned_long_long * _Nonnull atomic);
|
||||
bool catmc_atomic_unsigned_long_long_compare_and_exchange(struct catmc_atomic_unsigned_long_long * _Nonnull atomic, unsigned long long expected, unsigned long long desired);
|
||||
unsigned long long catmc_atomic_unsigned_long_long_add(struct catmc_atomic_unsigned_long_long * _Nonnull atomic, unsigned long long value);
|
||||
unsigned long long catmc_atomic_unsigned_long_long_sub(struct catmc_atomic_unsigned_long_long * _Nonnull atomic, unsigned long long value);
|
||||
unsigned long long catmc_atomic_unsigned_long_long_exchange(struct catmc_atomic_unsigned_long_long * _Nonnull atomic, unsigned long long value);
|
||||
unsigned long long catmc_atomic_unsigned_long_long_load(struct catmc_atomic_unsigned_long_long * _Nonnull atomic);
|
||||
void catmc_atomic_unsigned_long_long_store(struct catmc_atomic_unsigned_long_long * _Nonnull atomic, unsigned long long value);
|
||||
struct catmc_atomic_int_least8_t;
|
||||
struct catmc_atomic_int_least8_t * _Nonnull catmc_atomic_int_least8_t_create(int_least8_t value);
|
||||
void catmc_atomic_int_least8_t_destroy(struct catmc_atomic_int_least8_t * _Nonnull atomic);
|
||||
bool catmc_atomic_int_least8_t_compare_and_exchange(struct catmc_atomic_int_least8_t * _Nonnull atomic, int_least8_t expected, int_least8_t desired);
|
||||
int_least8_t catmc_atomic_int_least8_t_add(struct catmc_atomic_int_least8_t * _Nonnull atomic, int_least8_t value);
|
||||
int_least8_t catmc_atomic_int_least8_t_sub(struct catmc_atomic_int_least8_t * _Nonnull atomic, int_least8_t value);
|
||||
int_least8_t catmc_atomic_int_least8_t_exchange(struct catmc_atomic_int_least8_t * _Nonnull atomic, int_least8_t value);
|
||||
int_least8_t catmc_atomic_int_least8_t_load(struct catmc_atomic_int_least8_t * _Nonnull atomic);
|
||||
void catmc_atomic_int_least8_t_store(struct catmc_atomic_int_least8_t * _Nonnull atomic, int_least8_t value);
|
||||
struct catmc_atomic_uint_least8_t;
|
||||
struct catmc_atomic_uint_least8_t * _Nonnull catmc_atomic_uint_least8_t_create(uint_least8_t value);
|
||||
void catmc_atomic_uint_least8_t_destroy(struct catmc_atomic_uint_least8_t * _Nonnull atomic);
|
||||
bool catmc_atomic_uint_least8_t_compare_and_exchange(struct catmc_atomic_uint_least8_t * _Nonnull atomic, uint_least8_t expected, uint_least8_t desired);
|
||||
uint_least8_t catmc_atomic_uint_least8_t_add(struct catmc_atomic_uint_least8_t * _Nonnull atomic, uint_least8_t value);
|
||||
uint_least8_t catmc_atomic_uint_least8_t_sub(struct catmc_atomic_uint_least8_t * _Nonnull atomic, uint_least8_t value);
|
||||
uint_least8_t catmc_atomic_uint_least8_t_exchange(struct catmc_atomic_uint_least8_t * _Nonnull atomic, uint_least8_t value);
|
||||
uint_least8_t catmc_atomic_uint_least8_t_load(struct catmc_atomic_uint_least8_t * _Nonnull atomic);
|
||||
void catmc_atomic_uint_least8_t_store(struct catmc_atomic_uint_least8_t * _Nonnull atomic, uint_least8_t value);
|
||||
struct catmc_atomic_int_least16_t;
|
||||
struct catmc_atomic_int_least16_t * _Nonnull catmc_atomic_int_least16_t_create(int_least16_t value);
|
||||
void catmc_atomic_int_least16_t_destroy(struct catmc_atomic_int_least16_t * _Nonnull atomic);
|
||||
bool catmc_atomic_int_least16_t_compare_and_exchange(struct catmc_atomic_int_least16_t * _Nonnull atomic, int_least16_t expected, int_least16_t desired);
|
||||
int_least16_t catmc_atomic_int_least16_t_add(struct catmc_atomic_int_least16_t * _Nonnull atomic, int_least16_t value);
|
||||
int_least16_t catmc_atomic_int_least16_t_sub(struct catmc_atomic_int_least16_t * _Nonnull atomic, int_least16_t value);
|
||||
int_least16_t catmc_atomic_int_least16_t_exchange(struct catmc_atomic_int_least16_t * _Nonnull atomic, int_least16_t value);
|
||||
int_least16_t catmc_atomic_int_least16_t_load(struct catmc_atomic_int_least16_t * _Nonnull atomic);
|
||||
void catmc_atomic_int_least16_t_store(struct catmc_atomic_int_least16_t * _Nonnull atomic, int_least16_t value);
|
||||
struct catmc_atomic_uint_least16_t;
|
||||
struct catmc_atomic_uint_least16_t * _Nonnull catmc_atomic_uint_least16_t_create(uint_least16_t value);
|
||||
void catmc_atomic_uint_least16_t_destroy(struct catmc_atomic_uint_least16_t * _Nonnull atomic);
|
||||
bool catmc_atomic_uint_least16_t_compare_and_exchange(struct catmc_atomic_uint_least16_t * _Nonnull atomic, uint_least16_t expected, uint_least16_t desired);
|
||||
uint_least16_t catmc_atomic_uint_least16_t_add(struct catmc_atomic_uint_least16_t * _Nonnull atomic, uint_least16_t value);
|
||||
uint_least16_t catmc_atomic_uint_least16_t_sub(struct catmc_atomic_uint_least16_t * _Nonnull atomic, uint_least16_t value);
|
||||
uint_least16_t catmc_atomic_uint_least16_t_exchange(struct catmc_atomic_uint_least16_t * _Nonnull atomic, uint_least16_t value);
|
||||
uint_least16_t catmc_atomic_uint_least16_t_load(struct catmc_atomic_uint_least16_t * _Nonnull atomic);
|
||||
void catmc_atomic_uint_least16_t_store(struct catmc_atomic_uint_least16_t * _Nonnull atomic, uint_least16_t value);
|
||||
struct catmc_atomic_int_least32_t;
|
||||
struct catmc_atomic_int_least32_t * _Nonnull catmc_atomic_int_least32_t_create(int_least32_t value);
|
||||
void catmc_atomic_int_least32_t_destroy(struct catmc_atomic_int_least32_t * _Nonnull atomic);
|
||||
bool catmc_atomic_int_least32_t_compare_and_exchange(struct catmc_atomic_int_least32_t * _Nonnull atomic, int_least32_t expected, int_least32_t desired);
|
||||
int_least32_t catmc_atomic_int_least32_t_add(struct catmc_atomic_int_least32_t * _Nonnull atomic, int_least32_t value);
|
||||
int_least32_t catmc_atomic_int_least32_t_sub(struct catmc_atomic_int_least32_t * _Nonnull atomic, int_least32_t value);
|
||||
int_least32_t catmc_atomic_int_least32_t_exchange(struct catmc_atomic_int_least32_t * _Nonnull atomic, int_least32_t value);
|
||||
int_least32_t catmc_atomic_int_least32_t_load(struct catmc_atomic_int_least32_t * _Nonnull atomic);
|
||||
void catmc_atomic_int_least32_t_store(struct catmc_atomic_int_least32_t * _Nonnull atomic, int_least32_t value);
|
||||
struct catmc_atomic_uint_least32_t;
|
||||
struct catmc_atomic_uint_least32_t * _Nonnull catmc_atomic_uint_least32_t_create(uint_least32_t value);
|
||||
void catmc_atomic_uint_least32_t_destroy(struct catmc_atomic_uint_least32_t * _Nonnull atomic);
|
||||
bool catmc_atomic_uint_least32_t_compare_and_exchange(struct catmc_atomic_uint_least32_t * _Nonnull atomic, uint_least32_t expected, uint_least32_t desired);
|
||||
uint_least32_t catmc_atomic_uint_least32_t_add(struct catmc_atomic_uint_least32_t * _Nonnull atomic, uint_least32_t value);
|
||||
uint_least32_t catmc_atomic_uint_least32_t_sub(struct catmc_atomic_uint_least32_t * _Nonnull atomic, uint_least32_t value);
|
||||
uint_least32_t catmc_atomic_uint_least32_t_exchange(struct catmc_atomic_uint_least32_t * _Nonnull atomic, uint_least32_t value);
|
||||
uint_least32_t catmc_atomic_uint_least32_t_load(struct catmc_atomic_uint_least32_t * _Nonnull atomic);
|
||||
void catmc_atomic_uint_least32_t_store(struct catmc_atomic_uint_least32_t * _Nonnull atomic, uint_least32_t value);
|
||||
struct catmc_atomic_int_least64_t;
|
||||
struct catmc_atomic_int_least64_t * _Nonnull catmc_atomic_int_least64_t_create(int_least64_t value);
|
||||
void catmc_atomic_int_least64_t_destroy(struct catmc_atomic_int_least64_t * _Nonnull atomic);
|
||||
bool catmc_atomic_int_least64_t_compare_and_exchange(struct catmc_atomic_int_least64_t * _Nonnull atomic, int_least64_t expected, int_least64_t desired);
|
||||
int_least64_t catmc_atomic_int_least64_t_add(struct catmc_atomic_int_least64_t * _Nonnull atomic, int_least64_t value);
|
||||
int_least64_t catmc_atomic_int_least64_t_sub(struct catmc_atomic_int_least64_t * _Nonnull atomic, int_least64_t value);
|
||||
int_least64_t catmc_atomic_int_least64_t_exchange(struct catmc_atomic_int_least64_t * _Nonnull atomic, int_least64_t value);
|
||||
int_least64_t catmc_atomic_int_least64_t_load(struct catmc_atomic_int_least64_t * _Nonnull atomic);
|
||||
void catmc_atomic_int_least64_t_store(struct catmc_atomic_int_least64_t * _Nonnull atomic, int_least64_t value);
|
||||
struct catmc_atomic_uint_least64_t;
|
||||
struct catmc_atomic_uint_least64_t * _Nonnull catmc_atomic_uint_least64_t_create(uint_least64_t value);
|
||||
void catmc_atomic_uint_least64_t_destroy(struct catmc_atomic_uint_least64_t * _Nonnull atomic);
|
||||
bool catmc_atomic_uint_least64_t_compare_and_exchange(struct catmc_atomic_uint_least64_t * _Nonnull atomic, uint_least64_t expected, uint_least64_t desired);
|
||||
uint_least64_t catmc_atomic_uint_least64_t_add(struct catmc_atomic_uint_least64_t * _Nonnull atomic, uint_least64_t value);
|
||||
uint_least64_t catmc_atomic_uint_least64_t_sub(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);
|
||||
void catmc_atomic_uint_least64_t_store(struct catmc_atomic_uint_least64_t * _Nonnull atomic, uint_least64_t value);
|
|
@ -0,0 +1,452 @@
|
|||
//
|
||||
// this is https://github.com/18sg/uSHET/blob/master/lib/cpp_magic.h
|
||||
// LICENSE: MIT
|
||||
//
|
||||
//
|
||||
|
||||
/**
|
||||
* This header file contains a library of advanced C Pre-Processor (CPP) macros
|
||||
* which implement various useful functions, such as iteration, in the
|
||||
* pre-processor.
|
||||
*
|
||||
* Though the file name (quite validly) labels this as magic, there should be
|
||||
* enough documentation in the comments for a reader only casually familiar
|
||||
* with the CPP to be able to understand how everything works.
|
||||
*
|
||||
* The majority of the magic tricks used in this file are based on those
|
||||
* described by pfultz2 in his "Cloak" library:
|
||||
*
|
||||
* https://github.com/pfultz2/Cloak/wiki/C-Preprocessor-tricks,-tips,-and-idioms
|
||||
*
|
||||
* Major differences are a greater level of detailed explanation in this
|
||||
* implementation and also a refusal to include any macros which require a O(N)
|
||||
* macro definitions to handle O(N) arguments (with the exception of DEFERn).
|
||||
*/
|
||||
|
||||
#ifndef CPP_MAGIC_H
|
||||
#define CPP_MAGIC_H
|
||||
|
||||
/**
|
||||
* Force the pre-processor to expand the macro a large number of times. Usage:
|
||||
*
|
||||
* EVAL(expression)
|
||||
*
|
||||
* This is useful when you have a macro which evaluates to a valid macro
|
||||
* expression which is not subsequently expanded in the same pass. A contrived,
|
||||
* but easy to understand, example of such a macro follows. Note that though
|
||||
* this example is contrived, this behaviour is abused to implement bounded
|
||||
* recursion in macros such as FOR.
|
||||
*
|
||||
* #define A(x) x+1
|
||||
* #define EMPTY
|
||||
* #define NOT_QUITE_RIGHT(x) A EMPTY (x)
|
||||
* NOT_QUITE_RIGHT(999)
|
||||
*
|
||||
* Here's what happens inside the C preprocessor:
|
||||
*
|
||||
* 1. It sees a macro "NOT_QUITE_RIGHT" and performs a single macro expansion
|
||||
* pass on its arguments. Since the argument is "999" and this isn't a macro,
|
||||
* this is a boring step resulting in no change.
|
||||
* 2. The NOT_QUITE_RIGHT macro is substituted for its definition giving "A
|
||||
* EMPTY() (x)".
|
||||
* 3. The expander moves from left-to-right trying to expand the macro:
|
||||
* The first token, A, cannot be expanded since there are no brackets
|
||||
* immediately following it. The second token EMPTY(), however, can be
|
||||
* expanded (recursively in this manner) and is replaced with "".
|
||||
* 4. Expansion continues from the start of the substituted test (which in this
|
||||
* case is just empty), and sees "(999)" but since no macro name is present,
|
||||
* nothing is done. This results in a final expansion of "A (999)".
|
||||
*
|
||||
* Unfortunately, this doesn't quite meet expectations since you may expect that
|
||||
* "A (999)" would have been expanded into "999+1". Unfortunately this requires
|
||||
* a second expansion pass but luckily we can force the macro processor to make
|
||||
* more passes by abusing the first step of macro expansion: the preprocessor
|
||||
* expands arguments in their own pass. If we define a macro which does nothing
|
||||
* except produce its arguments e.g.:
|
||||
*
|
||||
* #define PASS_THROUGH(...) __VA_ARGS__
|
||||
*
|
||||
* We can now do "PASS_THROUGH(NOT_QUITE_RIGHT(999))" causing "NOT_QUITE_RIGHT" to be
|
||||
* expanded to "A (999)", as described above, when the arguments are expanded.
|
||||
* Now when the body of PASS_THROUGH is expanded, "A (999)" gets expanded to
|
||||
* "999+1".
|
||||
*
|
||||
* The EVAL defined below is essentially equivalent to a large nesting of
|
||||
* "PASS_THROUGH(PASS_THROUGH(PASS_THROUGH(..." which results in the
|
||||
* preprocessor making a large number of expansion passes over the given
|
||||
* expression.
|
||||
*/
|
||||
#define EVAL(...) EVAL1024(__VA_ARGS__)
|
||||
#define EVAL1024(...) EVAL512(EVAL512(__VA_ARGS__))
|
||||
#define EVAL512(...) EVAL256(EVAL256(__VA_ARGS__))
|
||||
#define EVAL256(...) EVAL128(EVAL128(__VA_ARGS__))
|
||||
#define EVAL128(...) EVAL64(EVAL64(__VA_ARGS__))
|
||||
#define EVAL64(...) EVAL32(EVAL32(__VA_ARGS__))
|
||||
#define EVAL32(...) EVAL16(EVAL16(__VA_ARGS__))
|
||||
#define EVAL16(...) EVAL8(EVAL8(__VA_ARGS__))
|
||||
#define EVAL8(...) EVAL4(EVAL4(__VA_ARGS__))
|
||||
#define EVAL4(...) EVAL2(EVAL2(__VA_ARGS__))
|
||||
#define EVAL2(...) EVAL1(EVAL1(__VA_ARGS__))
|
||||
#define EVAL1(...) __VA_ARGS__
|
||||
|
||||
|
||||
/**
|
||||
* Macros which expand to common values
|
||||
*/
|
||||
#define PASS(...) __VA_ARGS__
|
||||
#define EMPTY()
|
||||
#define COMMA() ,
|
||||
#define PLUS() +
|
||||
#define ZERO() 0
|
||||
#define ONE() 1
|
||||
|
||||
/**
|
||||
* Causes a function-style macro to require an additional pass to be expanded.
|
||||
*
|
||||
* This is useful, for example, when trying to implement recursion since the
|
||||
* recursive step must not be expanded in a single pass as the pre-processor
|
||||
* will catch it and prevent it.
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* DEFER1(IN_NEXT_PASS)(args, to, the, macro)
|
||||
*
|
||||
* How it works:
|
||||
*
|
||||
* 1. When DEFER1 is expanded, first its arguments are expanded which are
|
||||
* simply IN_NEXT_PASS. Since this is a function-style macro and it has no
|
||||
* arguments, nothing will happen.
|
||||
* 2. The body of DEFER1 will now be expanded resulting in EMPTY() being
|
||||
* deleted. This results in "IN_NEXT_PASS (args, to, the macro)". Note that
|
||||
* since the macro expander has already passed IN_NEXT_PASS by the time it
|
||||
* expands EMPTY() and so it won't spot that the brackets which remain can be
|
||||
* applied to IN_NEXT_PASS.
|
||||
* 3. At this point the macro expansion completes. If one more pass is made,
|
||||
* IN_NEXT_PASS(args, to, the, macro) will be expanded as desired.
|
||||
*/
|
||||
#define DEFER1(id) id EMPTY()
|
||||
|
||||
/**
|
||||
* As with DEFER1 except here n additional passes are required for DEFERn.
|
||||
*
|
||||
* The mechanism is analogous.
|
||||
*
|
||||
* Note that there doesn't appear to be a way of combining DEFERn macros in
|
||||
* order to achieve exponentially increasing defers e.g. as is done by EVAL.
|
||||
*/
|
||||
#define DEFER2(id) id EMPTY EMPTY()()
|
||||
#define DEFER3(id) id EMPTY EMPTY EMPTY()()()
|
||||
#define DEFER4(id) id EMPTY EMPTY EMPTY EMPTY()()()()
|
||||
#define DEFER5(id) id EMPTY EMPTY EMPTY EMPTY EMPTY()()()()()
|
||||
#define DEFER6(id) id EMPTY EMPTY EMPTY EMPTY EMPTY EMPTY()()()()()()
|
||||
#define DEFER7(id) id EMPTY EMPTY EMPTY EMPTY EMPTY EMPTY EMPTY()()()()()()()
|
||||
#define DEFER8(id) id EMPTY EMPTY EMPTY EMPTY EMPTY EMPTY EMPTY EMPTY()()()()()()()()
|
||||
|
||||
|
||||
/**
|
||||
* Indirection around the standard ## concatenation operator. This simply
|
||||
* ensures that the arguments are expanded (once) before concatenation.
|
||||
*/
|
||||
#define CAT(a, ...) a ## __VA_ARGS__
|
||||
#define CAT3(a, b, ...) a ## b ## __VA_ARGS__
|
||||
|
||||
|
||||
/**
|
||||
* Get the first argument and ignore the rest.
|
||||
*/
|
||||
#define FIRST(a, ...) a
|
||||
|
||||
/**
|
||||
* Get the second argument and ignore the rest.
|
||||
*/
|
||||
#define SECOND(a, b, ...) b
|
||||
|
||||
/**
|
||||
* Expects a single input (not containing commas). Returns 1 if the input is
|
||||
* PROBE() and otherwise returns 0.
|
||||
*
|
||||
* This can be useful as the basis of a NOT function.
|
||||
*
|
||||
* This macro abuses the fact that PROBE() contains a comma while other valid
|
||||
* inputs must not.
|
||||
*/
|
||||
#define IS_PROBE(...) SECOND(__VA_ARGS__, 0)
|
||||
#define PROBE() ~, 1
|
||||
|
||||
|
||||
/**
|
||||
* Logical negation. 0 is defined as false and everything else as true.
|
||||
*
|
||||
* When 0, _NOT_0 will be found which evaluates to the PROBE. When 1 (or any other
|
||||
* value) is given, an appropriately named macro won't be found and the
|
||||
* concatenated string will be produced. IS_PROBE then simply checks to see if
|
||||
* the PROBE was returned, cleanly converting the argument into a 1 or 0.
|
||||
*/
|
||||
#define NOT(x) IS_PROBE(CAT(_NOT_, x))
|
||||
#define _NOT_0 PROBE()
|
||||
|
||||
/**
|
||||
* Macro version of C's famous "cast to bool" operator (i.e. !!) which takes
|
||||
* anything and casts it to 0 if it is 0 and 1 otherwise.
|
||||
*/
|
||||
#define BOOL(x) NOT(NOT(x))
|
||||
|
||||
/**
|
||||
* Logical OR. Simply performs a lookup.
|
||||
*/
|
||||
#define OR(a,b) CAT3(_OR_, a, b)
|
||||
#define _OR_00 0
|
||||
#define _OR_01 1
|
||||
#define _OR_10 1
|
||||
#define _OR_11 1
|
||||
|
||||
/**
|
||||
* Logical AND. Simply performs a lookup.
|
||||
*/
|
||||
#define AND(a,b) CAT3(_AND_, a, b)
|
||||
#define _AND_00 0
|
||||
#define _AND_01 0
|
||||
#define _AND_10 0
|
||||
#define _AND_11 1
|
||||
|
||||
|
||||
/**
|
||||
* Macro if statement. Usage:
|
||||
*
|
||||
* IF(c)(expansion when true)
|
||||
*
|
||||
* Here's how:
|
||||
*
|
||||
* 1. The preprocessor expands the arguments to _IF casting the condition to '0'
|
||||
* or '1'.
|
||||
* 2. The casted condition is concatencated with _IF_ giving _IF_0 or _IF_1.
|
||||
* 3. The _IF_0 and _IF_1 macros either returns the argument or doesn't (e.g.
|
||||
* they implement the "choice selection" part of the macro).
|
||||
* 4. Note that the "true" clause is in the extra set of brackets; thus these
|
||||
* become the arguments to _IF_0 or _IF_1 and thus a selection is made!
|
||||
*/
|
||||
#define IF(c) _IF(BOOL(c))
|
||||
#define _IF(c) CAT(_IF_,c)
|
||||
#define _IF_0(...)
|
||||
#define _IF_1(...) __VA_ARGS__
|
||||
|
||||
/**
|
||||
* Macro if/else statement. Usage:
|
||||
*
|
||||
* IF_ELSE(c)( \
|
||||
* expansion when true, \
|
||||
* expansion when false \
|
||||
* )
|
||||
*
|
||||
* The mechanism is analogous to IF.
|
||||
*/
|
||||
#define IF_ELSE(c) _IF_ELSE(BOOL(c))
|
||||
#define _IF_ELSE(c) CAT(_IF_ELSE_,c)
|
||||
#define _IF_ELSE_0(t,f) f
|
||||
#define _IF_ELSE_1(t,f) t
|
||||
|
||||
|
||||
/**
|
||||
* Macro which checks if it has any arguments. Returns '0' if there are no
|
||||
* arguments, '1' otherwise.
|
||||
*
|
||||
* Limitation: HAS_ARGS(,1,2,3) returns 0 -- this check essentially only checks
|
||||
* that the first argument exists.
|
||||
*
|
||||
* This macro works as follows:
|
||||
*
|
||||
* 1. _END_OF_ARGUMENTS_ is concatenated with the first argument.
|
||||
* 2. If the first argument is not present then only "_END_OF_ARGUMENTS_" will
|
||||
* remain, otherwise "_END_OF_ARGUMENTS something_here" will remain. This
|
||||
* remaining argument can start with parentheses.
|
||||
* 3. In the former case, the _END_OF_ARGUMENTS_(0) macro expands to a
|
||||
* 0 when it is expanded. In the latter, a non-zero result remains. If the
|
||||
* first argument started with parentheses these will mostly not contain
|
||||
* only a single 0, but e.g a C cast or some arithmetic operation that will
|
||||
* cause the BOOL in _END_OF_ARGUMENTS_ to be one.
|
||||
* 4. BOOL is used to force non-zero results into 1 giving the clean 0 or 1
|
||||
* output required.
|
||||
*/
|
||||
#define HAS_ARGS(...) BOOL(FIRST(_END_OF_ARGUMENTS_ __VA_ARGS__)(0))
|
||||
#define _END_OF_ARGUMENTS_(...) BOOL(FIRST(__VA_ARGS__))
|
||||
|
||||
|
||||
/**
|
||||
* Macro map/list comprehension. Usage:
|
||||
*
|
||||
* MAP(op, sep, ...)
|
||||
*
|
||||
* Produces a 'sep()'-separated list of the result of op(arg) for each arg.
|
||||
*
|
||||
* Example Usage:
|
||||
*
|
||||
* #define MAKE_HAPPY(x) happy_##x
|
||||
* #define COMMA() ,
|
||||
* MAP(MAKE_HAPPY, COMMA, 1,2,3)
|
||||
*
|
||||
* Which expands to:
|
||||
*
|
||||
* happy_1 , happy_2 , happy_3
|
||||
*
|
||||
* How it works:
|
||||
*
|
||||
* 1. The MAP macro simply maps the inner MAP_INNER function in an EVAL which
|
||||
* forces it to be expanded a large number of times, thus enabling many steps
|
||||
* of iteration (see step 6).
|
||||
* 2. The MAP_INNER macro is substituted for its body.
|
||||
* 3. In the body, op(cur_val) is substituted giving the value for this
|
||||
* iteration.
|
||||
* 4. The IF macro expands according to whether further iterations are required.
|
||||
* This expansion either produces _IF_0 or _IF_1.
|
||||
* 5. Since the IF is followed by a set of brackets containing the "if true"
|
||||
* clause, these become the argument to _IF_0 or _IF_1. At this point, the
|
||||
* macro in the brackets will be expanded giving the separator followed by
|
||||
* _MAP_INNER EMPTY()()(op, sep, __VA_ARGS__).
|
||||
* 5. If the IF was not taken, the above will simply be discarded and everything
|
||||
* stops. If the IF is taken, The expression is then processed a second time
|
||||
* yielding "_MAP_INNER()(op, sep, __VA_ARGS__)". Note that this call looks
|
||||
* very similar to the essentially the same as the original call except the
|
||||
* first argument has been dropped.
|
||||
* 6. At this point expansion of MAP_INNER will terminate. However, since we can
|
||||
* force more rounds of expansion using EVAL1. In the argument-expansion pass
|
||||
* of the EVAL1, _MAP_INNER() is expanded to MAP_INNER which is then expanded
|
||||
* using the arguments which follow it as in step 2-5. This is followed by a
|
||||
* second expansion pass as the substitution of EVAL1() is expanded executing
|
||||
* 2-5 a second time. This results in up to two iterations occurring. Using
|
||||
* many nested EVAL1 macros, i.e. the very-deeply-nested EVAL macro, will in
|
||||
* this manner produce further iterations, hence the outer MAP macro doing
|
||||
* this for us.
|
||||
*
|
||||
* Important tricks used:
|
||||
*
|
||||
* * If we directly produce "MAP_INNER" in an expansion of MAP_INNER, a special
|
||||
* case in the preprocessor will prevent it being expanded in the future, even
|
||||
* if we EVAL. As a result, the MAP_INNER macro carefully only expands to
|
||||
* something containing "_MAP_INNER()" which requires a further expansion step
|
||||
* to invoke MAP_INNER and thus implementing the recursion.
|
||||
* * To prevent _MAP_INNER being expanded within the macro we must first defer its
|
||||
* expansion during its initial pass as an argument to _IF_0 or _IF_1. We must
|
||||
* then defer its expansion a second time as part of the body of the _IF_0. As
|
||||
* a result hence the DEFER2.
|
||||
* * _MAP_INNER seemingly gets away with producing itself because it actually only
|
||||
* produces MAP_INNER. It just happens that when _MAP_INNER() is expanded in
|
||||
* this case it is followed by some arguments which get consumed by MAP_INNER
|
||||
* and produce a _MAP_INNER. As such, the macro expander never marks
|
||||
* _MAP_INNER as expanding to itself and thus it will still be expanded in
|
||||
* future productions of itself.
|
||||
*/
|
||||
#define MAP(...) \
|
||||
IF(HAS_ARGS(__VA_ARGS__))(EVAL(MAP_INNER(__VA_ARGS__)))
|
||||
#define MAP_INNER(op,sep,cur_val, ...) \
|
||||
op(cur_val) \
|
||||
IF(HAS_ARGS(__VA_ARGS__))( \
|
||||
sep() DEFER2(_MAP_INNER)()(op, sep, ##__VA_ARGS__) \
|
||||
)
|
||||
#define _MAP_INNER() MAP_INNER
|
||||
|
||||
|
||||
/**
|
||||
* This is a variant of the MAP macro which also includes as an argument to the
|
||||
* operation a valid C variable name which is different for each iteration.
|
||||
*
|
||||
* Usage:
|
||||
* MAP_WITH_ID(op, sep, ...)
|
||||
*
|
||||
* Where op is a macro op(val, id) which takes a list value and an ID. This ID
|
||||
* will simply be a unary number using the digit "I", that is, I, II, III, IIII,
|
||||
* and so on.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* #define MAKE_STATIC_VAR(type, name) static type name;
|
||||
* MAP_WITH_ID(MAKE_STATIC_VAR, EMPTY, int, int, int, bool, char)
|
||||
*
|
||||
* Which expands to:
|
||||
*
|
||||
* static int I; static int II; static int III; static bool IIII; static char IIIII;
|
||||
*
|
||||
* The mechanism is analogous to the MAP macro.
|
||||
*/
|
||||
#define MAP_WITH_ID(op,sep,...) \
|
||||
IF(HAS_ARGS(__VA_ARGS__))(EVAL(MAP_WITH_ID_INNER(op,sep,I, ##__VA_ARGS__)))
|
||||
#define MAP_WITH_ID_INNER(op,sep,id,cur_val, ...) \
|
||||
op(cur_val,id) \
|
||||
IF(HAS_ARGS(__VA_ARGS__))( \
|
||||
sep() DEFER2(_MAP_WITH_ID_INNER)()(op, sep, CAT(id,I), ##__VA_ARGS__) \
|
||||
)
|
||||
#define _MAP_WITH_ID_INNER() MAP_WITH_ID_INNER
|
||||
|
||||
|
||||
/**
|
||||
* This is a variant of the MAP macro which iterates over pairs rather than
|
||||
* singletons.
|
||||
*
|
||||
* Usage:
|
||||
* MAP_PAIRS(op, sep, ...)
|
||||
*
|
||||
* Where op is a macro op(val_1, val_2) which takes two list values.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* #define MAKE_STATIC_VAR(type, name) static type name;
|
||||
* MAP_PAIRS(MAKE_STATIC_VAR, EMPTY, char, my_char, int, my_int)
|
||||
*
|
||||
* Which expands to:
|
||||
*
|
||||
* static char my_char; static int my_int;
|
||||
*
|
||||
* The mechanism is analogous to the MAP macro.
|
||||
*/
|
||||
#define MAP_PAIRS(op,sep,...) \
|
||||
IF(HAS_ARGS(__VA_ARGS__))(EVAL(MAP_PAIRS_INNER(op,sep,__VA_ARGS__)))
|
||||
#define MAP_PAIRS_INNER(op,sep,cur_val_1, cur_val_2, ...) \
|
||||
op(cur_val_1,cur_val_2) \
|
||||
IF(HAS_ARGS(__VA_ARGS__))( \
|
||||
sep() DEFER2(_MAP_PAIRS_INNER)()(op, sep, __VA_ARGS__) \
|
||||
)
|
||||
#define _MAP_PAIRS_INNER() MAP_PAIRS_INNER
|
||||
|
||||
/**
|
||||
* This is a variant of the MAP macro which iterates over a two-element sliding
|
||||
* window.
|
||||
*
|
||||
* Usage:
|
||||
* MAP_SLIDE(op, last_op, sep, ...)
|
||||
*
|
||||
* Where op is a macro op(val_1, val_2) which takes the two list values
|
||||
* currently in the window. last_op is a macro taking a single value which is
|
||||
* called for the last argument.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* #define SIMON_SAYS_OP(simon, next) IF(NOT(simon()))(next)
|
||||
* #define SIMON_SAYS_LAST_OP(val) last_but_not_least_##val
|
||||
* #define SIMON_SAYS() 0
|
||||
*
|
||||
* MAP_SLIDE(SIMON_SAYS_OP, SIMON_SAYS_LAST_OP, EMPTY, wiggle, SIMON_SAYS, dance, move, SIMON_SAYS, boogie, stop)
|
||||
*
|
||||
* Which expands to:
|
||||
*
|
||||
* dance boogie last_but_not_least_stop
|
||||
*
|
||||
* The mechanism is analogous to the MAP macro.
|
||||
*/
|
||||
#define MAP_SLIDE(op,last_op,sep,...) \
|
||||
IF(HAS_ARGS(__VA_ARGS__))(EVAL(MAP_SLIDE_INNER(op,last_op,sep,__VA_ARGS__)))
|
||||
#define MAP_SLIDE_INNER(op,last_op,sep,cur_val, ...) \
|
||||
IF(HAS_ARGS(__VA_ARGS__))(op(cur_val,FIRST(__VA_ARGS__))) \
|
||||
IF(NOT(HAS_ARGS(__VA_ARGS__)))(last_op(cur_val)) \
|
||||
IF(HAS_ARGS(__VA_ARGS__))( \
|
||||
sep() DEFER2(_MAP_SLIDE_INNER)()(op, last_op, sep, __VA_ARGS__) \
|
||||
)
|
||||
#define _MAP_SLIDE_INNER() MAP_SLIDE_INNER
|
||||
|
||||
|
||||
/**
|
||||
* Strip any excess commas from a set of arguments.
|
||||
*/
|
||||
#define REMOVE_TRAILING_COMMAS(...) \
|
||||
MAP(PASS, COMMA, __VA_ARGS__)
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,104 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdatomic.h>
|
||||
#include <stdbool.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../include/c-atomics.h"
|
||||
#include "../include/cpp_magic.h"
|
||||
|
||||
struct catmc_atomic_flag {
|
||||
atomic_flag _flag;
|
||||
};
|
||||
|
||||
struct catmc_atomic_flag *catmc_atomic_flag_create(bool value) {
|
||||
struct catmc_atomic_flag *flag = malloc(sizeof(*flag));
|
||||
flag->_flag = (__typeof__(flag->_flag))ATOMIC_FLAG_INIT;
|
||||
if (value) {
|
||||
(void)atomic_flag_test_and_set_explicit(&flag->_flag, memory_order_relaxed);
|
||||
} else {
|
||||
atomic_flag_clear_explicit(&flag->_flag, memory_order_relaxed);
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
void catmc_atomic_flag_destroy(struct catmc_atomic_flag *flag) {
|
||||
free(flag);
|
||||
}
|
||||
|
||||
#define MAKE(type) /*
|
||||
*/ struct catmc_atomic_##type { /*
|
||||
*/ _Atomic type value; /*
|
||||
*/ }; /*
|
||||
*/ /*
|
||||
*/ struct catmc_atomic_##type *catmc_atomic_##type##_create(type value) { /*
|
||||
*/ struct catmc_atomic_##type *wrapper = malloc(sizeof(*wrapper)); /*
|
||||
*/ atomic_init(&wrapper->value, value); /*
|
||||
*/ return wrapper; /*
|
||||
*/ } /*
|
||||
*/ /*
|
||||
*/ void catmc_atomic_##type##_destroy(struct catmc_atomic_##type *wrapper) { /*
|
||||
*/ free(wrapper); /*
|
||||
*/ } /*
|
||||
*/ /*
|
||||
*/ bool catmc_atomic_##type##_compare_and_exchange(struct catmc_atomic_##type *wrapper, type expected, type desired) { /*
|
||||
*/ type expected_copy = expected; /*
|
||||
*/ return atomic_compare_exchange_strong(&wrapper->value, &expected_copy, desired); /*
|
||||
*/ } /*
|
||||
*/ /*
|
||||
*/ type catmc_atomic_##type##_add(struct catmc_atomic_##type *wrapper, type value) { /*
|
||||
*/ return atomic_fetch_add_explicit(&wrapper->value, value, memory_order_relaxed); /*
|
||||
*/ } /*
|
||||
*/ /*
|
||||
*/ type catmc_atomic_##type##_sub(struct catmc_atomic_##type *wrapper, type value) { /*
|
||||
*/ return atomic_fetch_sub_explicit(&wrapper->value, value, memory_order_relaxed); /*
|
||||
*/ } /*
|
||||
*/ /*
|
||||
*/ type catmc_atomic_##type##_exchange(struct catmc_atomic_##type *wrapper, type value) { /*
|
||||
*/ return atomic_exchange_explicit(&wrapper->value, value, memory_order_relaxed); /*
|
||||
*/ } /*
|
||||
*/ /*
|
||||
*/ type catmc_atomic_##type##_load(struct catmc_atomic_##type *wrapper) { /*
|
||||
*/ return atomic_load_explicit(&wrapper->value, memory_order_relaxed); /*
|
||||
*/ } /*
|
||||
*/ /*
|
||||
*/ void catmc_atomic_##type##_store(struct catmc_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
|
||||
)
|
|
@ -12,7 +12,7 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import ConcurrencyHelpers
|
||||
import NIOConcurrencyHelpers
|
||||
|
||||
#if os(Linux)
|
||||
import Glibc
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import ConcurrencyHelpers
|
||||
import NIOConcurrencyHelpers
|
||||
import Dispatch
|
||||
import class Foundation.Thread
|
||||
import SwiftPriorityQueue
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import ConcurrencyHelpers
|
||||
import NIOConcurrencyHelpers
|
||||
|
||||
|
||||
public enum EventLoopFutureValue<T> {
|
||||
|
|
|
@ -0,0 +1,183 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
|
||||
public final class Atomic<T: AtomicPrimitive> {
|
||||
private let value: OpaquePointer
|
||||
|
||||
public init(value: T) {
|
||||
self.value = T.atomic_create(value)
|
||||
}
|
||||
|
||||
public func compareAndExchange(expected: T, desired: T) -> Bool {
|
||||
return T.atomic_compare_and_exchange(self.value, expected, desired)
|
||||
}
|
||||
|
||||
public func add(_ rhs: T) -> T {
|
||||
return T.atomic_add(self.value, rhs)
|
||||
}
|
||||
|
||||
public func sub(_ rhs: T) -> T {
|
||||
return T.atomic_sub(self.value, rhs)
|
||||
}
|
||||
|
||||
public func exchange(with value: T) -> T {
|
||||
return T.atomic_exchange(self.value, value)
|
||||
}
|
||||
|
||||
public func load() -> T {
|
||||
return T.atomic_load(self.value)
|
||||
}
|
||||
|
||||
public func store(_ value: T) -> Void {
|
||||
T.atomic_store(self.value, value)
|
||||
}
|
||||
|
||||
deinit {
|
||||
T.atomic_destroy(self.value)
|
||||
}
|
||||
}
|
||||
|
||||
public protocol AtomicPrimitive {
|
||||
static var atomic_create: (Self) -> OpaquePointer { get }
|
||||
static var atomic_destroy: (OpaquePointer) -> Void { get }
|
||||
static var atomic_compare_and_exchange: (OpaquePointer, Self, Self) -> Bool { get }
|
||||
static var atomic_add: (OpaquePointer, Self) -> Self { get }
|
||||
static var atomic_sub: (OpaquePointer, Self) -> Self { get }
|
||||
static var atomic_exchange: (OpaquePointer, Self) -> Self { get }
|
||||
static var atomic_load: (OpaquePointer) -> Self { get }
|
||||
static var atomic_store: (OpaquePointer, Self) -> Void { get }
|
||||
}
|
||||
|
||||
extension Bool: AtomicPrimitive {
|
||||
public static let atomic_create = catmc_atomic__Bool_create
|
||||
public static let atomic_destroy = catmc_atomic__Bool_destroy
|
||||
public static let atomic_compare_and_exchange = catmc_atomic__Bool_compare_and_exchange
|
||||
public static let atomic_add = catmc_atomic__Bool_add
|
||||
public static let atomic_sub = catmc_atomic__Bool_sub
|
||||
public static let atomic_exchange = catmc_atomic__Bool_exchange
|
||||
public static let atomic_load = catmc_atomic__Bool_load
|
||||
public static let atomic_store = catmc_atomic__Bool_store
|
||||
}
|
||||
|
||||
extension Int8: AtomicPrimitive {
|
||||
public static let atomic_create = catmc_atomic_int_least8_t_create
|
||||
public static let atomic_destroy = catmc_atomic_int_least8_t_destroy
|
||||
public static let atomic_compare_and_exchange = catmc_atomic_int_least8_t_compare_and_exchange
|
||||
public static let atomic_add = catmc_atomic_int_least8_t_add
|
||||
public static let atomic_sub = catmc_atomic_int_least8_t_sub
|
||||
public static let atomic_exchange = catmc_atomic_int_least8_t_exchange
|
||||
public static let atomic_load = catmc_atomic_int_least8_t_load
|
||||
public static let atomic_store = catmc_atomic_int_least8_t_store
|
||||
}
|
||||
|
||||
extension UInt8: AtomicPrimitive {
|
||||
public static let atomic_create = catmc_atomic_uint_least8_t_create
|
||||
public static let atomic_destroy = catmc_atomic_uint_least8_t_destroy
|
||||
public static let atomic_compare_and_exchange = catmc_atomic_uint_least8_t_compare_and_exchange
|
||||
public static let atomic_add = catmc_atomic_uint_least8_t_add
|
||||
public static let atomic_sub = catmc_atomic_uint_least8_t_sub
|
||||
public static let atomic_exchange = catmc_atomic_uint_least8_t_exchange
|
||||
public static let atomic_load = catmc_atomic_uint_least8_t_load
|
||||
public static let atomic_store = catmc_atomic_uint_least8_t_store
|
||||
}
|
||||
|
||||
extension Int16: AtomicPrimitive {
|
||||
public static let atomic_create = catmc_atomic_int_least16_t_create
|
||||
public static let atomic_destroy = catmc_atomic_int_least16_t_destroy
|
||||
public static let atomic_compare_and_exchange = catmc_atomic_int_least16_t_compare_and_exchange
|
||||
public static let atomic_add = catmc_atomic_int_least16_t_add
|
||||
public static let atomic_sub = catmc_atomic_int_least16_t_sub
|
||||
public static let atomic_exchange = catmc_atomic_int_least16_t_exchange
|
||||
public static let atomic_load = catmc_atomic_int_least16_t_load
|
||||
public static let atomic_store = catmc_atomic_int_least16_t_store
|
||||
}
|
||||
|
||||
extension UInt16: AtomicPrimitive {
|
||||
public static let atomic_create = catmc_atomic_uint_least16_t_create
|
||||
public static let atomic_destroy = catmc_atomic_uint_least16_t_destroy
|
||||
public static let atomic_compare_and_exchange = catmc_atomic_uint_least16_t_compare_and_exchange
|
||||
public static let atomic_add = catmc_atomic_uint_least16_t_add
|
||||
public static let atomic_sub = catmc_atomic_uint_least16_t_sub
|
||||
public static let atomic_exchange = catmc_atomic_uint_least16_t_exchange
|
||||
public static let atomic_load = catmc_atomic_uint_least16_t_load
|
||||
public static let atomic_store = catmc_atomic_uint_least16_t_store
|
||||
}
|
||||
|
||||
extension Int32: AtomicPrimitive {
|
||||
public static let atomic_create = catmc_atomic_int_least32_t_create
|
||||
public static let atomic_destroy = catmc_atomic_int_least32_t_destroy
|
||||
public static let atomic_compare_and_exchange = catmc_atomic_int_least32_t_compare_and_exchange
|
||||
public static let atomic_add = catmc_atomic_int_least32_t_add
|
||||
public static let atomic_sub = catmc_atomic_int_least32_t_sub
|
||||
public static let atomic_exchange = catmc_atomic_int_least32_t_exchange
|
||||
public static let atomic_load = catmc_atomic_int_least32_t_load
|
||||
public static let atomic_store = catmc_atomic_int_least32_t_store
|
||||
}
|
||||
|
||||
extension UInt32: AtomicPrimitive {
|
||||
public static let atomic_create = catmc_atomic_uint_least32_t_create
|
||||
public static let atomic_destroy = catmc_atomic_uint_least32_t_destroy
|
||||
public static let atomic_compare_and_exchange = catmc_atomic_uint_least32_t_compare_and_exchange
|
||||
public static let atomic_add = catmc_atomic_uint_least32_t_add
|
||||
public static let atomic_sub = catmc_atomic_uint_least32_t_sub
|
||||
public static let atomic_exchange = catmc_atomic_uint_least32_t_exchange
|
||||
public static let atomic_load = catmc_atomic_uint_least32_t_load
|
||||
public static let atomic_store = catmc_atomic_uint_least32_t_store
|
||||
}
|
||||
|
||||
extension Int64: AtomicPrimitive {
|
||||
public static let atomic_create = catmc_atomic_long_long_create
|
||||
public static let atomic_destroy = catmc_atomic_long_long_destroy
|
||||
public static let atomic_compare_and_exchange = catmc_atomic_long_long_compare_and_exchange
|
||||
public static let atomic_add = catmc_atomic_long_long_add
|
||||
public static let atomic_sub = catmc_atomic_long_long_sub
|
||||
public static let atomic_exchange = catmc_atomic_long_long_exchange
|
||||
public static let atomic_load = catmc_atomic_long_long_load
|
||||
public static let atomic_store = catmc_atomic_long_long_store
|
||||
}
|
||||
|
||||
extension UInt64: AtomicPrimitive {
|
||||
public static let atomic_create = catmc_atomic_unsigned_long_long_create
|
||||
public static let atomic_destroy = catmc_atomic_unsigned_long_long_destroy
|
||||
public static let atomic_compare_and_exchange = catmc_atomic_unsigned_long_long_compare_and_exchange
|
||||
public static let atomic_add = catmc_atomic_unsigned_long_long_add
|
||||
public static let atomic_sub = catmc_atomic_unsigned_long_long_sub
|
||||
public static let atomic_exchange = catmc_atomic_unsigned_long_long_exchange
|
||||
public static let atomic_load = catmc_atomic_unsigned_long_long_load
|
||||
public static let atomic_store = catmc_atomic_unsigned_long_long_store
|
||||
}
|
||||
|
||||
extension Int: AtomicPrimitive {
|
||||
public static let atomic_create = catmc_atomic_long_create
|
||||
public static let atomic_destroy = catmc_atomic_long_destroy
|
||||
public static let atomic_compare_and_exchange = catmc_atomic_long_compare_and_exchange
|
||||
public static let atomic_add = catmc_atomic_long_add
|
||||
public static let atomic_sub = catmc_atomic_long_sub
|
||||
public static let atomic_exchange = catmc_atomic_long_exchange
|
||||
public static let atomic_load = catmc_atomic_long_load
|
||||
public static let atomic_store = catmc_atomic_long_store
|
||||
}
|
||||
|
||||
extension UInt: AtomicPrimitive {
|
||||
public static let atomic_create = catmc_atomic_unsigned_long_create
|
||||
public static let atomic_destroy = catmc_atomic_unsigned_long_destroy
|
||||
public static let atomic_compare_and_exchange = catmc_atomic_unsigned_long_compare_and_exchange
|
||||
public static let atomic_add = catmc_atomic_unsigned_long_add
|
||||
public static let atomic_sub = catmc_atomic_unsigned_long_sub
|
||||
public static let atomic_exchange = catmc_atomic_unsigned_long_exchange
|
||||
public static let atomic_load = catmc_atomic_unsigned_long_load
|
||||
public static let atomic_store = catmc_atomic_unsigned_long_store
|
||||
}
|
|
@ -0,0 +1,140 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
import Darwin
|
||||
#else
|
||||
import Glibc
|
||||
#endif
|
||||
|
||||
public final class Lock {
|
||||
fileprivate let mutex: UnsafeMutablePointer<pthread_mutex_t> = UnsafeMutablePointer.allocate(capacity: 1)
|
||||
|
||||
public init() {
|
||||
let err = pthread_mutex_init(self.mutex, nil)
|
||||
precondition(err == 0)
|
||||
}
|
||||
|
||||
deinit {
|
||||
mutex.deallocate(capacity: 1)
|
||||
}
|
||||
|
||||
public func lock() {
|
||||
let err = pthread_mutex_lock(self.mutex)
|
||||
precondition(err == 0)
|
||||
}
|
||||
|
||||
public func unlock() {
|
||||
let err = pthread_mutex_unlock(self.mutex)
|
||||
precondition(err == 0)
|
||||
}
|
||||
}
|
||||
|
||||
extension Lock {
|
||||
public func withLock<T>(_ fn: () throws -> T) rethrows -> T {
|
||||
self.lock()
|
||||
defer {
|
||||
self.unlock()
|
||||
}
|
||||
return try fn()
|
||||
}
|
||||
|
||||
// specialise Void return (for performance)
|
||||
public func withLockVoid(_ fn: () throws -> Void) rethrows -> Void {
|
||||
try self.withLock(fn)
|
||||
}
|
||||
}
|
||||
|
||||
public final class ConditionLock<T: Equatable> {
|
||||
private var _value: T
|
||||
private let mutex: Lock
|
||||
private let cond: UnsafeMutablePointer<pthread_cond_t> = UnsafeMutablePointer.allocate(capacity: 1)
|
||||
|
||||
public init(value: T) {
|
||||
self._value = value
|
||||
self.mutex = Lock()
|
||||
let err = pthread_cond_init(self.cond, nil)
|
||||
precondition(err == 0)
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.cond.deallocate(capacity: 1)
|
||||
}
|
||||
|
||||
public func lock() {
|
||||
self.mutex.lock()
|
||||
}
|
||||
|
||||
public func unlock() {
|
||||
self.mutex.unlock()
|
||||
}
|
||||
|
||||
public var value: T {
|
||||
self.lock()
|
||||
defer {
|
||||
self.unlock()
|
||||
}
|
||||
return self._value
|
||||
}
|
||||
|
||||
public func lock(whenValue wantedValue: T) {
|
||||
self.lock()
|
||||
while true {
|
||||
if self._value == wantedValue {
|
||||
break
|
||||
}
|
||||
let err = pthread_cond_wait(self.cond, self.mutex.mutex)
|
||||
precondition(err == 0, "pthread_cond_wait error \(err)")
|
||||
}
|
||||
}
|
||||
|
||||
public func lock(whenValue wantedValue: T, timeoutSeconds: Double) -> Bool{
|
||||
precondition(timeoutSeconds >= 0)
|
||||
|
||||
let nsecPerSec: Int64 = 1000000000
|
||||
self.lock()
|
||||
/* the timeout as a (seconds, nano seconds) pair */
|
||||
let timeoutNS = Int64(timeoutSeconds * Double(nsecPerSec))
|
||||
|
||||
var curTime = timeval()
|
||||
gettimeofday(&curTime, nil)
|
||||
|
||||
let allNSecs: Int64 = timeoutNS + Int64(curTime.tv_usec) * 1000
|
||||
var timeoutAbs = timespec(tv_sec: curTime.tv_sec + Int((allNSecs / nsecPerSec)),
|
||||
tv_nsec: Int(allNSecs % nsecPerSec))
|
||||
assert(timeoutAbs.tv_nsec >= 0 && timeoutAbs.tv_nsec < Int(nsecPerSec))
|
||||
assert(timeoutAbs.tv_sec >= curTime.tv_sec)
|
||||
while true {
|
||||
if self._value == wantedValue {
|
||||
return true
|
||||
}
|
||||
switch pthread_cond_timedwait(self.cond, self.mutex.mutex, &timeoutAbs) {
|
||||
case 0:
|
||||
continue
|
||||
case ETIMEDOUT:
|
||||
self.unlock()
|
||||
return false
|
||||
case let e:
|
||||
fatalError("caught error \(e) when calling pthread_cond_timedwait")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func unlock(withValue newValue: T) {
|
||||
self._value = newValue
|
||||
self.unlock()
|
||||
let r = pthread_cond_broadcast(self.cond)
|
||||
precondition(r == 0)
|
||||
}
|
||||
}
|
|
@ -23,6 +23,7 @@ import XCTest
|
|||
///
|
||||
|
||||
#if os(Linux) || os(FreeBSD)
|
||||
@testable import NIOConcurrencyHelpersTests
|
||||
@testable import NIOHTTP1Tests
|
||||
@testable import NIOOpenSSLTests
|
||||
@testable import NIOTLSTests
|
||||
|
@ -59,6 +60,7 @@ import XCTest
|
|||
testCase(SSLPrivateKeyTest.allTests),
|
||||
testCase(SniHandlerTest.allTests),
|
||||
testCase(SocketAddressTest.allTests),
|
||||
testCase(NIOConcurrencyHelpersTests.allTests),
|
||||
testCase(SystemTest.allTests),
|
||||
testCase(TLSConfigurationTest.allTests),
|
||||
testCase(TypeAssistedChannelHandlerTest.allTests),
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// NIOConcurrencyHelpersTests+XCTest.swift
|
||||
///
|
||||
import XCTest
|
||||
|
||||
///
|
||||
/// NOTE: This file was generated by generate_linux_tests.rb
|
||||
///
|
||||
/// Do NOT edit this file directly as it will be regenerated automatically when needed.
|
||||
///
|
||||
|
||||
extension NIOConcurrencyHelpersTests {
|
||||
|
||||
static var allTests : [(String, (NIOConcurrencyHelpersTests) -> () throws -> Void)] {
|
||||
return [
|
||||
("testLargeContentedAtomicSum", testLargeContentedAtomicSum),
|
||||
("testCompareAndExchangeBool", testCompareAndExchangeBool),
|
||||
("testAllOperationsBool", testAllOperationsBool),
|
||||
("testCompareAndExchangeUInts", testCompareAndExchangeUInts),
|
||||
("testCompareAndExchangeInts", testCompareAndExchangeInts),
|
||||
("testAddSub", testAddSub),
|
||||
("testExchange", testExchange),
|
||||
("testLoadStore", testLoadStore),
|
||||
("testLockMutualExclusion", testLockMutualExclusion),
|
||||
("testWithLockMutualExclusion", testWithLockMutualExclusion),
|
||||
("testConditionLockMutualExclusion", testConditionLockMutualExclusion),
|
||||
("testConditionLock", testConditionLock),
|
||||
("testConditionLockWithDifferentConditions", testConditionLockWithDifferentConditions),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,404 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
import Darwin
|
||||
#else
|
||||
import Glibc
|
||||
#endif
|
||||
import Dispatch
|
||||
import XCTest
|
||||
@testable import NIOConcurrencyHelpers
|
||||
|
||||
class NIOConcurrencyHelpersTests: XCTestCase {
|
||||
private func sumOfIntegers(until n: UInt64) -> UInt64 {
|
||||
return n*(n+1)/2
|
||||
}
|
||||
|
||||
func testLargeContentedAtomicSum() {
|
||||
let noAsyncs: UInt64 = 64
|
||||
let noCounts: UInt64 = 200_000
|
||||
|
||||
let q = DispatchQueue(label: "q", attributes: .concurrent)
|
||||
let g = DispatchGroup()
|
||||
let ai = NIOConcurrencyHelpers.Atomic<UInt64>(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 testCompareAndExchangeBool() {
|
||||
let ab = Atomic<Bool>(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 testAllOperationsBool() {
|
||||
let ab = Atomic<Bool>(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 testCompareAndExchangeUInts() {
|
||||
func testFor<T: AtomicPrimitive & FixedWidthInteger & UnsignedInteger>(_ value: T.Type) {
|
||||
let zero: T = 0
|
||||
let max = ~zero
|
||||
|
||||
let ab = Atomic<T>(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 testCompareAndExchangeInts() {
|
||||
func testFor<T: AtomicPrimitive & FixedWidthInteger & SignedInteger>(_ value: T.Type) {
|
||||
let zero: T = 0
|
||||
let upperBound: T = 127
|
||||
|
||||
let ab = Atomic<T>(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 testAddSub() {
|
||||
func testFor<T: AtomicPrimitive & FixedWidthInteger>(_ value: T.Type) {
|
||||
let zero: T = 0
|
||||
|
||||
let ab = Atomic<T>(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 testExchange() {
|
||||
func testFor<T: AtomicPrimitive & FixedWidthInteger>(_ value: T.Type) {
|
||||
let zero: T = 0
|
||||
|
||||
let ab = Atomic<T>(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 testLoadStore() {
|
||||
func testFor<T: AtomicPrimitive & FixedWidthInteger>(_ value: T.Type) {
|
||||
let zero: T = 0
|
||||
|
||||
let ab = Atomic<T>(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()
|
||||
|
||||
var x = 1
|
||||
let q = DispatchQueue(label: "q")
|
||||
let g = DispatchGroup()
|
||||
let sem1 = DispatchSemaphore(value: 0)
|
||||
let sem2 = DispatchSemaphore(value: 0)
|
||||
|
||||
l.lock()
|
||||
|
||||
q.async(group: g) {
|
||||
sem1.signal()
|
||||
l.lock()
|
||||
x = 2
|
||||
l.unlock()
|
||||
sem2.signal()
|
||||
}
|
||||
|
||||
sem1.wait()
|
||||
XCTAssertEqual(DispatchTimeoutResult.timedOut,
|
||||
g.wait(timeout: .now() + 0.1))
|
||||
XCTAssertEqual(1, x)
|
||||
|
||||
l.unlock()
|
||||
sem2.wait()
|
||||
|
||||
l.lock()
|
||||
XCTAssertEqual(2, x)
|
||||
l.unlock()
|
||||
}
|
||||
|
||||
func testWithLockMutualExclusion() {
|
||||
let l = Lock()
|
||||
|
||||
var x = 1
|
||||
let q = DispatchQueue(label: "q")
|
||||
let g = DispatchGroup()
|
||||
let sem1 = DispatchSemaphore(value: 0)
|
||||
let sem2 = DispatchSemaphore(value: 0)
|
||||
|
||||
l.withLock {
|
||||
q.async(group: g) {
|
||||
sem1.signal()
|
||||
l.withLock {
|
||||
x = 2
|
||||
}
|
||||
sem2.signal()
|
||||
}
|
||||
|
||||
sem1.wait()
|
||||
XCTAssertEqual(DispatchTimeoutResult.timedOut,
|
||||
g.wait(timeout: .now() + 0.1))
|
||||
XCTAssertEqual(1, x)
|
||||
}
|
||||
sem2.wait()
|
||||
|
||||
l.withLock {
|
||||
XCTAssertEqual(2, x)
|
||||
}
|
||||
}
|
||||
|
||||
func testConditionLockMutualExclusion() {
|
||||
let l = ConditionLock(value: 0)
|
||||
|
||||
var x = 1
|
||||
let q = DispatchQueue(label: "q")
|
||||
let g = DispatchGroup()
|
||||
let sem1 = DispatchSemaphore(value: 0)
|
||||
let sem2 = DispatchSemaphore(value: 0)
|
||||
|
||||
l.lock()
|
||||
|
||||
q.async(group: g) {
|
||||
sem1.signal()
|
||||
l.lock()
|
||||
x = 2
|
||||
l.unlock()
|
||||
sem2.signal()
|
||||
}
|
||||
|
||||
sem1.wait()
|
||||
XCTAssertEqual(DispatchTimeoutResult.timedOut,
|
||||
g.wait(timeout: .now() + 0.1))
|
||||
XCTAssertEqual(1, x)
|
||||
|
||||
l.unlock()
|
||||
sem2.wait()
|
||||
|
||||
l.lock()
|
||||
XCTAssertEqual(2, x)
|
||||
l.unlock()
|
||||
}
|
||||
|
||||
func testConditionLock() {
|
||||
let l = ConditionLock(value: 0)
|
||||
let q = DispatchQueue(label: "q")
|
||||
let sem = DispatchSemaphore(value: 0)
|
||||
|
||||
XCTAssertEqual(0, l.value)
|
||||
|
||||
l.lock()
|
||||
l.unlock(withValue: 1)
|
||||
|
||||
XCTAssertEqual(1, l.value)
|
||||
|
||||
q.async {
|
||||
l.lock(whenValue: 2)
|
||||
l.unlock(withValue: 3)
|
||||
sem.signal()
|
||||
}
|
||||
|
||||
usleep(100_000)
|
||||
|
||||
l.lock()
|
||||
l.unlock(withValue: 2)
|
||||
|
||||
sem.wait()
|
||||
l.lock(whenValue: 3)
|
||||
l.unlock()
|
||||
|
||||
XCTAssertEqual(false, l.lock(whenValue: 4, timeoutSeconds: 0.1))
|
||||
|
||||
XCTAssertEqual(true, l.lock(whenValue: 3, timeoutSeconds: 0.01))
|
||||
l.unlock()
|
||||
|
||||
q.async {
|
||||
usleep(100_000)
|
||||
|
||||
l.lock()
|
||||
l.unlock(withValue: 4)
|
||||
sem.signal()
|
||||
}
|
||||
|
||||
XCTAssertEqual(true, l.lock(whenValue: 4, timeoutSeconds: 10))
|
||||
l.unlock()
|
||||
}
|
||||
|
||||
func testConditionLockWithDifferentConditions() {
|
||||
for _ in 0..<200 {
|
||||
let l = ConditionLock(value: 0)
|
||||
let q1 = DispatchQueue(label: "q1")
|
||||
let q2 = DispatchQueue(label: "q2")
|
||||
|
||||
let readySem = DispatchSemaphore(value: 0)
|
||||
let doneSem = DispatchSemaphore(value: 0)
|
||||
|
||||
q1.async {
|
||||
readySem.signal()
|
||||
|
||||
l.lock(whenValue: 1)
|
||||
l.unlock()
|
||||
XCTAssertEqual(1, l.value)
|
||||
|
||||
doneSem.signal()
|
||||
}
|
||||
|
||||
q2.async {
|
||||
readySem.signal()
|
||||
|
||||
l.lock(whenValue: 2)
|
||||
l.unlock()
|
||||
XCTAssertEqual(2, l.value)
|
||||
|
||||
doneSem.signal()
|
||||
}
|
||||
|
||||
readySem.wait()
|
||||
readySem.wait()
|
||||
l.lock()
|
||||
l.unlock(withValue: 1)
|
||||
|
||||
doneSem.wait() /* job on 'q1' is done */
|
||||
|
||||
XCTAssertEqual(1, l.value)
|
||||
l.lock()
|
||||
l.unlock(withValue: 2)
|
||||
|
||||
doneSem.wait() /* job on 'q2' is done */
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import XCTest
|
||||
import ConcurrencyHelpers
|
||||
import NIOConcurrencyHelpers
|
||||
import NIO
|
||||
import Dispatch
|
||||
@testable import NIOHTTP1
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import XCTest
|
||||
import ConcurrencyHelpers
|
||||
import NIOConcurrencyHelpers
|
||||
@testable import NIO
|
||||
|
||||
class ChannelPipelineTest: XCTestCase {
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import XCTest
|
||||
import ConcurrencyHelpers
|
||||
import NIOConcurrencyHelpers
|
||||
import Dispatch
|
||||
@testable import NIO
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
import XCTest
|
||||
import NIO
|
||||
import Dispatch
|
||||
import ConcurrencyHelpers
|
||||
import NIOConcurrencyHelpers
|
||||
|
||||
public class EventLoopTest : XCTestCase {
|
||||
|
||||
|
|
Loading…
Reference in New Issue