Начало работы
Установка* Поместите x.h в свой проект.
Использование* x.h — это библиотека с одним заголовком, что означает, что пользователи могут просто использовать её функциональные возможности, включив её где угодно:
// в каком-то файле foo.h
#include "x.h"
// в каком-то файле foo.c
#include "x.h"
Документация
#ifndef X_ENABLE_ATOMIC
#define X_ENABLE_ATOMIC (0)
#endif
#ifndef X_ENABLE_CONCURRENCY
#define X_ENABLE_CONCURRENCY (0)
#endif
#ifndef X_ENABLE_CUDA
#define X_ENABLE_CUDA (0)
#endif
#ifndef X_ENABLE_SOCKET
#define X_ENABLE_SOCKET (0)
#endif
#ifndef X_ENABLE_STRUCT_FUNCTION
#define X_ENABLE_STRUCT_FUNCTION (1)
#endif
Большой диапазон патчей позволяет номеру версии работать с _MSC_FULL_VER.
X_32BIT: определяется как 1, если архитектура 32-битная, иначе 0.
X_64BIT: определяется как 1, если архитектура 64-битная, иначе 0.
X_ARM: определяется как 1, если архитектура ARM, иначе 0. Иначе.
X_ARM64: определяется как 1, если архитектура 64-битная ARM, иначе 0.
X_X86: определяется как 1, если архитектура 32-битная x86, иначе 0.
X_X64: определяется как 1, если архитектура 64-битная x86, иначе 0.
Определение компилятора
Номер версии генерируется с помощью X_VER. Например, X_VER(15, 0, 6) (версия 15.0.6) приводит к результату 150000006.
Обнаружение ОС
Обнаружение платформы
X_EXPORT, X_IMPORT
#ifndef X_EXPORT
#if X_WINDOWS
#define X_EXPORT __declspec(dllexport)
#else
#define X_EXPORT __attribute__ ((visibility("default")))
#endif
#endif
#ifndef X_IMPORT
#if X_WINDOWS
#define X_IMPORT __declspec(dllimport)
#else
#define X_IMPORT __attribute__ ((visibility("hidden")))
#endif
#endif
См. Microsoft Docs и GCC Wiki для получения дополнительной информации.
X_KEY
#define X_KEY_ESC (0x1B)
#define X_KEY_A (0x41)
#define X_KEY_B (0x42)
#define X_KEY_C (0x43)
#define X_KEY_D (0x44)
#define X_KEY_Q (0x51)
#if X_WINDOWS
#define X_KEY_LEFT (0x4B)
#define X_KEY_UP (0x48)
#define X_KEY_RIGHT (0x4D)
#define X_KEY_DOWN (0x50)
#else
#define X_KEY_LEFT (-1)
#define X_KEY_UP (-2)
#define X_KEY_RIGHT (-3)
#define X_KEY_DOWN (-4)
#endif
Несколько макросов виртуальных клавиш, большинство из которых определяются соответствующим ASCII-кодом. Однако стрелки обрабатываются по-разному в разных ОС (пожалуйста, сообщите мне, если это утверждение неверно), они определены как отрицательные целые числа для обхода. Пожалуйста, проверьте x_getch для их использования.
x_assert Макрос, который включает функцию утверждения для сборок отладки и выпуска. Для сборки отладки это то же самое, что и макрос утверждения в заголовке assert.h/cassert.
x_assert(expr)
expr
: выражение утверждения.x_assert(1 == 1);
x_assert(1 != 1);
x_bit
Макрос, используемый для генерации целого числа, в котором только n-й бит установлен в 1. Это полезно, когда нужно перечисления вроде 0b0001
, 0b0010
, 0b0100
для выполнения операций &
, |
, ~
.
T x_bit(bit) // В этом документе T обозначает тип возвращаемого значения из макроса.
bit
: спецификация, для какого бита целого числа должен быть установлен 1.int
, long
и т. д.enum
{
FLAG_NONE = 0,
FLAG_READ = x_bit(1),
FLAG_WRITE = x_bit(2),
};
int read_and_write = FLAG_READ | FLAG_WRITE;
x_buffer_valid Определение этого макроса должно было хорошо объяснить себя:
#define x_buffer_valid(buffer, size) \
(((buffer) == NULL && (size) == 0) || ((buffer) != NULL && (size) != 0))
Он не реализован как функция, поскольку size
может быть int
, size_t
и т.д. Поэтому передавайте аргументы осторожно.
buffer
: указатель на буфер.size
: размер содержимого в указателе.true
, если буфер действителен.int read_file(const char* file, void* buffer, size_t size)
{
if (!x_buffer_valid(buffer,
``` **size)) {**
вернуть EINVAL;
}
// operations
вернуть 0;
}
Получить длину массива. Этот макрос работает только со статическими массивами.
T x_count(array)
Для C++ это реализовано как шаблонная функция:
template<class T, size_t N>
size_t x_count(const T (&array)[N])
{
return N;
}
array
: массив, размер которого нужно запросить.int a[5] = {1, 2, 3, 4, 5};
for (size_t i = 0; i < x_count(a); ++i)
{
printf("%d", a[i]);
}
Макрос для проверки, указывает ли номер ошибки на сбой. Работает только с системой обработки ошибок, которая определяет 0
как успех, например, POSIX errno.
bool x_fail(err)
err
: номер ошибки.Логическое значение, указывающее, означает ли номер ошибки сбой.
int err = EINVAL;
if (x_fail(err))
{
printf("%s\n", strerror(err));
}
Макрос для освобождения блока памяти, выделенного в куче, и установки его в NULL.
void x_free(ptr)
ptr
: указатель, которому ранее была выделена память.int *a = (int*)malloc(5 * sizeof(int));
x_free(a);
Макрос для получения константы Пи. Входной аргумент используется для указания целевого типа данных.
T x_Pi(T)
В C++ можно использовать следующий шаблон:
template<class T>
static constexpr T x_Pi = (T)3.141592653589793238462643383279502884197169399375;
// Использование: x_Pi<float>, x_Pi<double>, и т. д.
T
: целевой тип, например float
, double
, long
.float a = x_pi(float);
double b = x_pi(double);
Макрос для проверки, указывает ли номер ошибки на успех. Работает только с системой обработки ошибок, которая определяет 0
как успех, например, POSIX errno.
bool x_succ(err)
err
: номер ошибки.Логическое значение, указывающее, означает ли номер ошибки успех.
int err = 0;
if (x_succ(err))
{
printf("%s\n", strerror(err));
}
size_t x_cpu_count()
Количество процессоров текущего хоста.
double x_duration(const struct timespec start, const struct timespec end, const char* unit)
start
: начальная точка времени.end
: конечная точка времени.unit
: единица результата.Длительность двух временных точек в указанной единице.
long long x_file_size(const char* file)
file
: имя файла, размер которого необходимо проверить.Размер файла в байтах.
const char* x_full_path(char* dst, const char* src)
dst
: полный/абсолютный путь к входному файлу. Перед передачей этой функции он должен быть размещён в памяти, иначе будет возвращено NULL
.src
: (возможно, относительный) путь к файлу.То же значение, содержащееся в dst
, или NULL
, если операция не удалась.
const char* file = "./foo/bar.txt";
char buf[X_PATH_MAX] = {0};
x_full_path(buf, file);
Кроссплатформенная версия функции Win32 _getch.
int x_getch()
Нажатую клавишу.
Эта функция работает только с консольными программами. Её можно использовать для прерывания бесконечного цикла вручную:
int main(int argc, char** argv)
{
while (true)
{
if (x_getch() == X_KEY_ESC)
{
break; // При нажатии клавиши «Esc» цикл прерывается.
}
x_sleep(10);
}
return 0;
}
struct timespec x_now();
Экземпляр struct timespec
, указывающий текущее время.
bool x_path_exist(const char* path)
path
: путь к файлу или каталогу. for
// определение метода запроса сообщения об ошибке и самого метода. Пожалуйста,
// проверьте test/test_x_err.c, который должен быть самоочевидным.
//
// В противном случае описание будет получено в соответствии со значением
// ошибки через FormatMessage из Win32 API или strerror из POSIX.
const char* x_err_msg(char* msg, const size_t msz, const x_err err, ...
/* const int method, const char* generator*/);// Создаёт экземпляр x_err. x_err x_err_set(const int32_t cat, const int32_val);
// Может использоваться для инициализации экземпляра x_err. x_err x_ok();
#### Примеры
Пожалуйста, проверьте *test/test_x_err.c* и *test/test_x_err.cu*.
---
### Параллелизм
Эти функции во многом похожи на те, что предоставляются библиотекой поддержки параллелизма C11
- x\_cnd: утилиты условных переменных.
- x\_mtx: утилиты мьютекса.
- x\_sem: семафорные утилиты.
- x\_thd: утилиты потоков.
- x\_atomic\_B: атомарные утилиты 8-битных, 16-битных, 32-битных, 64-битных данных, bool, указателей (`void*`), флагов. Структуры и функции генерируются макросами во время компиляции.
Доступные типы атомарных данных:
- x\_atomic\_8: содержит данные `uint8_t`.
- x\_atomic\_16: содержит данные `uint16_t`.
- x\_atomic\_32: содержит данные `uint32_t`.
- x\_atomic\_64: содержит данные `uint64_t`.
- x\_atomic\_ptr: содержит данные типа `uint32_t` или `uint64_t` (`sizeof(void*)`, зависит от архитектуры).
- x\_atomic\_bool: содержит данные `_Bool`.
- x\_atomic_flag: содержит данные `_Bool`.
Доступные атомарные функции (где `B` — один из `8`, `16`, `32`, `64`, `ptr`,
`bool`, а `T` — один из `uint8_t`, `uint16_t`, `uint32_t`, `uint64_t`, `void*`,
'bool'):
```c
void x_atomic_init_B(volatile x_atomic_B* obj, T desired)
void x_atomic_store_B(volatile x_atomic_B* obj, T desired, x_memory_order order)
T x_atomic_load_B(volatile x_atomic_B* obj, x_memory_order order)
T x_atomic_exchange_B(volatile x_atomic_B* obj, T desired, x_memory_order order)
bool x_atomic_compare_exchange_B(
volatile x_atomic_B* obj, T* expected, T desired,
x_memory_order succ, x_memory_order fail)
T x_atomic_fetch_add_B(volatile x_atomic_B* obj, T desired, x_memory_order order)
T x_atomic_fetch_sub_B(volatile x_atomic_B* obj, T desired, x_memory_order order)
T x_atomic_fetch_Or_B(volatile x_atomic_B* obj, T desired, x_memory_order order)
T x_atomic_fetch_Xor_B(volatile x_atomic_B* obj, T desired, x_memory_order order)
T x_atomic_fetch_And_B(volatile x_atomic_B* obj, T desired, x_memory_order order)
#define x_kill_dependency(x) (x)
#define x_atomic_is_lock_free(T) _x_is_size_lock_free(sizeof(T))
bool x_atomic_flag_test_and_set(volatile x_atomic_flag* obj, x_memory_order order)
void x_atomic_flag_clear(volatile x_atomic_flag* obj, x_memory_order order)
void x_atomic_signal_fence(const x_memory_order order)
void x_atomic_thread_fence(const x_memory_order order)
Функциональные указатели внутри x_atomic_B
предоставляются унифицированным API, чтобы различные атомарные объекты можно было легко заменить во время рефакторинга кода. Например:
// before
x_atomic_32 obj = X_ATOMIC_VAR_INIT(32); // был 32-битный тип данных
obj.init(&obj, 0);
obj.fetch_add(&obj, 1);
// after
x_atomic_64 obj = X_ATOMIC_VAR_INIT(64); // рефакторинг до 64-битного
obj.init(&obj, 0); // нет необходимости это менять
obj.fetch_add(&obj, 1); // это тоже, ура!
Определение x_memory_order
:
typedef enum _x_memory_order_
{
#if X_CLANG || X_GCC
x_mo_relaxed = __ATOMIC_RELAXED,
x_mo_consume = __ATOMIC_CONSUME,
x_mo_acquire = __ATOMIC_ACQUIRE,
x_mo_release = __ATOMIC_RELEASE,
x_mo_acq_rel = __ATOMIC_ACQ_REL,
x_mo_seq_cst = __ATOMIC_SEQ_CST
#else
x_mo_relaxed = 0,
x_mo_consume = 1,
x_mo_acquire = 2,
x_mo_release = 3,
x_mo_acq_rel = 4,
x_mo_seq_cst = 5
#endif
} x_memory_order;
За исключением x_atomic_bool
и x_atomic_flag
, объекты x_atomic_B
заботятся только о том, сколько битов имеет внутренний тип данных. Поэтому при сохранении или загрузке данных в эти атомарные объекты следует выполнять правильное приведение типов. CRC-32 (on the fly) Checksum
uint32_t x_cks_crc32(const void* data, const size_t size, const uint32_t* prev)
data
: Исходные данные контрольной суммы.size
: Размер данных в байтах.prev
: Необязательный предыдущий результат контрольной суммы. Может быть NULL
.Контрольная сумма заголовка IPv4
uint16_t x_cks_rfc1071(const void* data, const size_t size)
data
: Исходные данные контрольной суммы.size
: Размер данных в байтах.Контрольная сумма XOR
uint8_t x_cks_xor(const void* data, const size_t size)
data
: Исходные данные контрольной суммы.size
: Размер данных в байтах.data
.Утилиты для работы с пакетами. Исходный код должен был объяснить сам себя.
Утилиты вектора ввода-вывода. Исходный код должен был объяснить сам себя.
Утилиты сокетов.
Узлы для связанных очередей и списков.
Простая двусторонняя очередь без синхронизации.
Очередь без блокировки.
Двухблокировочная очередь.
Утилиты для записи времени выполнения кода.
typedef struct _x_tictoc_
{
struct timespec start; // Временная метка начала записи.
double elapsed; // Время выполнения последнего цикла.
struct
{
bool ready; // Устанавливается в значение `true`, как только достигаются целевые циклы выполнения.
size_t cyc; // Общее количество циклов, которые должны быть записаны.
double sum; // Общее затраченное время.
double avg; // Среднее время выполнения на цикл.
struct
{
size_t idx; // Индекс цикла, в котором произошло максимальное/минимальное время выполнения.
double val; // Время выполнения `idx`-го цикла.
} max, min; // Информация о максимальном (max) и минимальном (min) времени выполнения.
} report;
} x_tictoc;
X_INLINE int x_tictoc_init(x_tictoc* tictoc);
// Начало отсчёта времени.
X_INLINE int x_tic(x_tictoc* tictoc, const bool echo);
// Конец отсчёта времени.
X_INLINE int x_toc(x_tictoc* tictoc, const char* unit, const bool echo);
// Конец отсчёта времени в многоцикловой операции записи.
X_INLINE int x_toc_ex(
x_tictoc* tictoc,
const char* unit, const long long cycle, const char* title,
char* echo, size_t* size);
Распространяется под лицензией Mulan PSL v2. Подробнее см. LICENSE.
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )