// ===== CodeLab: C11 新特性:标准 C 的多线程与原子时代 =====
// 来源: https://aoerliang.dpdns.org/articles/c11-features
// 以下代码片段按文章出现顺序拼接, 共 6 段

// ----- 片段 1 (c) -----
#include <stdio.h>

// 根据实参类型选择不同字符串
#define DESCRIBE(x) _Generic((x), \
    int: "整数", \
    double: "浮点数", \
    default: "其他类型")

int main(void) {
    int a = 42;
    double b = 3.14;
    char *s = "hi";
    printf("%s\n", DESCRIBE(a)); // 整数
    printf("%s\n", DESCRIBE(b)); // 浮点数
    printf("%s\n", DESCRIBE(s)); // 其他类型
    return 0;
}

// ----- 片段 2 (c) -----
// 更实用的例子:一个名字,多个实现
int sqi(int x) { return x * x; }
double sqd(double x) { return x * x; }

#define SQUARE(x) _Generic((x), int: sqi, double: sqd)(x)

int main(void) {
    printf("%d\n", SQUARE(5));     // 25
    printf("%.1f\n", SQUARE(2.5)); // 6.2
    return 0;
}

// ----- 片段 3 (c) -----
#include <stdalign.h>
#include <stddef.h>   // size_t

// 编译期断言:条件为假时编译失败
_Static_assert(sizeof(long) >= 8, "此代码需要 64 位平台");

// 指定 16 字节对齐的缓冲区
_Alignas(16) char buffer[64];

// 查询类型的对齐要求
size_t a = _Alignof(double); // 多数平台为 8

// ----- 片段 4 (c) -----
#include <stdio.h>
#include <stdatomic.h>
#include <threads.h>

atomic_long counter = 0;

int worker(void *arg) {
    for (int i = 0; i < 1000000; i++) {
        atomic_fetch_add(&counter, 1);
    }
    return 0;
}

int main(void) {
    thrd_t t1, t2;
    thrd_create(&t1, worker, NULL);
    thrd_create(&t2, worker, NULL);
    thrd_join(t1, NULL);
    thrd_join(t2, NULL);
    // 结果一定是 2000000,不会丢更新
    printf("counter = %ld\n", atomic_load(&counter));
    return 0;
}

// ----- 片段 5 (c) -----
#include <stdio.h>
#include <threads.h>

mtx_t mutex;
long counter = 0;

int worker(void *arg) {
    for (int i = 0; i < 100000; i++) {
        mtx_lock(&mutex);
        counter++;
        mtx_unlock(&mutex);
    }
    return 0;
}

int main(void) {
    thrd_t t1, t2;
    mtx_init(&mutex, mtx_plain);
    thrd_create(&t1, worker, NULL);
    thrd_create(&t2, worker, NULL);
    thrd_join(t1, NULL);
    thrd_join(t2, NULL);
    mtx_destroy(&mutex);
    printf("counter = %ld\n", counter);
    return 0;
}

// ----- 片段 6 (c) -----
/* 编译普通 C11 程序 */
/* gcc -std=c11 -o demo demo.c */

/* 用到线程 / 原子操作时 */
/* gcc -std=c11 -pthread -o demo demo.c */
