1. -run 脚本模式完善
- shebang 脚本 (#!/usr/bin/env pcc -run) 支持
- -rstdin 自定义输入、argv 参数传递
- win32/pcc-run.cmd 便捷启动器
2. -O2 优化等级
- -O0/-O1/-O2/-O3/-Os 全等级验证
- __OPTIMIZE__ 宏正确设置,常量折叠生效
3. C17 全特性
- 默认标准改为 C11 (__STDC_VERSION__=201112L)
- 新增 -std=c17/c18/c99/c89 支持
- _Generic/_Atomic/_Alignas/匿名结构/TLS 全通过
4. pcmake 构建工具 (tools/)
- 纯 C 编写,用 pcc 自身编译
- pcmake.conf 配置: sources/include/libs/output/flags
- CreateProcess 正确处理带空格路径
- pcmake.bat 一键构建 + clean
- 示例: examples/demo 多文件项目
5. 多线程库封装
- win32/include/pthread.h: POSIX 线程 Windows 实现
(CreateThread 封装, 事件驱动条件变量, 惰性初始化互斥锁)
- win32/include/threads.h: C11 标准线程 <threads.h>
- 4线程并发/互斥/条件变量/生产者消费者 测试通过
151 行
4.5 KiB
C
151 行
4.5 KiB
C
/*
|
|
* threads.h - C11 threads for Windows (PCC)
|
|
*
|
|
* Implements the C11 <threads.h> interface on top of the
|
|
* Win32 thread APIs. C11 threads are a thin wrapper around
|
|
* threads, mutexes, condition variables and TLS.
|
|
*
|
|
* License: MIT
|
|
*/
|
|
|
|
#ifndef _PCC_THREADS_H
|
|
#define _PCC_THREADS_H
|
|
|
|
#include <time.h>
|
|
#include "pthread.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/* ---------- types ---------- */
|
|
|
|
typedef pthread_t thrd_t;
|
|
typedef pthread_mutex_t mtx_t;
|
|
typedef pthread_cond_t cnd_t;
|
|
typedef pthread_key_t tss_t;
|
|
typedef int (*thrd_start_t)(void *);
|
|
typedef void (*tss_dtor_t)(void *);
|
|
|
|
typedef struct {
|
|
int type; /* unused */
|
|
} mtx_t_attr;
|
|
|
|
/* thread start wrapper: convert int(*)(void*) to void*(*)(void*) */
|
|
static void *thrd_wrapper(void *arg)
|
|
{
|
|
thrd_start_t fn = (thrd_start_t)((void **)arg)[0];
|
|
void *data = ((void **)arg)[1];
|
|
int result = fn(data);
|
|
free(arg);
|
|
return (void *)(intptr_t)result;
|
|
}
|
|
|
|
/* ---------- constants ---------- */
|
|
|
|
enum {
|
|
thrd_success = 0,
|
|
thrd_nomem = 1,
|
|
thrd_timedout = 2,
|
|
thrd_busy = 3,
|
|
thrd_error = 4
|
|
};
|
|
|
|
enum {
|
|
mtx_plain = 0,
|
|
mtx_timed = 1,
|
|
mtx_recursive = 2
|
|
};
|
|
|
|
#define TSS_DTOR_ITERATIONS 4
|
|
|
|
/* ---------- thread functions ---------- */
|
|
|
|
static int thrd_create(thrd_t *thr, thrd_start_t func, void *arg)
|
|
{
|
|
void **box = (void **)malloc(2 * sizeof(void *));
|
|
if (!box) return thrd_nomem;
|
|
box[0] = (void *)func;
|
|
box[1] = arg;
|
|
if (pthread_create(thr, NULL, thrd_wrapper, box) != 0) {
|
|
free(box);
|
|
return thrd_error;
|
|
}
|
|
return thrd_success;
|
|
}
|
|
|
|
static int thrd_equal(thrd_t a, thrd_t b) { return pthread_equal(a, b); }
|
|
static thrd_t thrd_current(void) { return pthread_self(); }
|
|
static int thrd_sleep(const struct timespec *duration, struct timespec *remaining)
|
|
{
|
|
DWORD ms = (DWORD)(duration->tv_sec * 1000 + duration->tv_nsec / 1000000);
|
|
(void)remaining;
|
|
Sleep(ms);
|
|
return 0;
|
|
}
|
|
static void thrd_yield(void) { Sleep(0); }
|
|
static void thrd_exit(int res) { pthread_exit((void *)(intptr_t)res); }
|
|
static int thrd_detach(thrd_t t) { return pthread_detach(t) ? thrd_error : thrd_success; }
|
|
|
|
static int thrd_join(thrd_t t, int *res)
|
|
{
|
|
void *ret;
|
|
if (pthread_join(t, &ret) != 0) return thrd_error;
|
|
if (res) *res = (int)(intptr_t)ret;
|
|
return thrd_success;
|
|
}
|
|
|
|
/* ---------- mutex functions ---------- */
|
|
|
|
static int mtx_init(mtx_t *mtx, int type)
|
|
{
|
|
(void)type;
|
|
return pthread_mutex_init(mtx, NULL) ? thrd_error : thrd_success;
|
|
}
|
|
static void mtx_destroy(mtx_t *mtx) { pthread_mutex_destroy(mtx); }
|
|
static int mtx_lock(mtx_t *mtx) { return pthread_mutex_lock(mtx) ? thrd_error : thrd_success; }
|
|
static int mtx_trylock(mtx_t *mtx) { return pthread_mutex_trylock(mtx) ? thrd_busy : thrd_success; }
|
|
static int mtx_unlock(mtx_t *mtx) { return pthread_mutex_unlock(mtx) ? thrd_error : thrd_success; }
|
|
static int mtx_timedlock(mtx_t *mtx, const struct timespec *at)
|
|
{
|
|
(void)mtx; (void)at;
|
|
return mtx_lock(mtx);
|
|
}
|
|
|
|
/* ---------- condition variable functions ---------- */
|
|
|
|
static int cnd_init(cnd_t *cond) { return pthread_cond_init(cond, NULL) ? thrd_error : thrd_success; }
|
|
static void cnd_destroy(cnd_t *cond) { pthread_cond_destroy(cond); }
|
|
static int cnd_signal(cnd_t *cond) { return pthread_cond_signal(cond) ? thrd_error : thrd_success; }
|
|
static int cnd_broadcast(cnd_t *cond) { return pthread_cond_broadcast(cond) ? thrd_error : thrd_success; }
|
|
static int cnd_wait(cnd_t *cond, mtx_t *mtx) { return pthread_cond_wait(cond, mtx) ? thrd_error : thrd_success; }
|
|
static int cnd_timedwait(cnd_t *cond, mtx_t *mtx, const struct timespec *at)
|
|
{
|
|
int r = pthread_cond_timedwait(cond, mtx, at);
|
|
if (r == 110) return thrd_timedout;
|
|
return r ? thrd_error : thrd_success;
|
|
}
|
|
|
|
/* ---------- TSS (thread-specific storage) ---------- */
|
|
|
|
static int tss_create(tss_t *key, tss_dtor_t dtor)
|
|
{
|
|
(void)dtor;
|
|
return pthread_key_create(key, NULL) ? thrd_error : thrd_success;
|
|
}
|
|
static void tss_delete(tss_t key) { pthread_key_delete(key); }
|
|
static void *tss_get(tss_t key) { return pthread_getspecific(key); }
|
|
static int tss_set(tss_t key, void *val) { return pthread_setspecific(key, val) ? thrd_error : thrd_success; }
|
|
|
|
/* ---------- call_once ---------- */
|
|
|
|
typedef pthread_once_control_t once_flag;
|
|
#define ONCE_FLAG_INIT PTHREAD_ONCE_INIT
|
|
static void call_once(once_flag *flag, void (*func)(void)) { pthread_once(flag, func); }
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* _PCC_THREADS_H */
|