测试代码
#include <stdio.h>
#include <threads.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include "unistd.h"
thrd_t thread_1 = 0;
thrd_t thread_2 = 0;
thrd_t thread_3 = 0;
thrd_t thread_4 = 0;
thrd_t thread_5 = 0;
thrd_t thread_6 = 0;
thrd_t thread_7 = 0;
thrd_t thread_8 = 0;
int thread1(void* param)
{
puts("thread1 start");
int run_time = 0;
while(1)
{
run_time++;
sleep(1);
printf("thread1:run_time=%d\n",run_time);
if(run_time==5)
{
thrd_exit(123);
puts("thread1 exit."); //不会执行
}
}
}
int thread2(void* param)
{
puts("thread2 start");
int thread1_result = 0;
int run_time = 0;
while(1)
{
run_time++;
sleep(1);
printf("thread2:run_time=%d\n",run_time);
if(run_time==3)
{
puts("thread2:thrd_join(thread_1, &thread1_result)");
int err = thrd_join(thread_1, &thread1_result);
printf("err=%d\n", err);
printf("thread1_result=%d\n", thread1_result);
}
if(run_time==6)
{
puts("thread2 exit.");
thrd_exit(0);
puts("thread2 exited."); //不会执行
}
}
}
int thread3(void* param)
{
puts("thread3 start");
int thread1_result = 0;
int run_time = 0;
while(1)
{
run_time++;
sleep(1);
printf("thread3:run_time=%d\n",run_time);
if(run_time==5)
{
thrd_t curthr_id = thrd_current();
if(thrd_equal(curthr_id, thread_3))
{
printf("thread3: curthr_id equal thread_3\n");
}
printf("thread3:curthr_id=%ld\n", curthr_id);
}
if(run_time==6)
{
puts("thread3 exit.");
thrd_exit(0);
}
}
}
int thread4(void* param)
{
puts("thread4 start");
int thread1_result = 0;
int run_time = 0;
while(1)
{
run_time++;
sleep(1);
printf("thread4:run_time=%d\n",run_time);
if(run_time==3)
{
puts("thread4:thrd_detach(thread_3)");
int err = thrd_detach(thread_3); //分离线程3, 使其资源在线程结束后自动释放
printf("err=%d\n", err);
}
if(run_time==8)
{
puts("thread4 exit.");
thrd_exit(0);
}
}
}
int thread6(void* param)
{
puts("thread6 start");
int run_time = 0;
while(1)
{
run_time++;
sleep(1);
printf("thread6:run_time=%d\n",run_time);
if(run_time==5)
{
puts("thread6 exit.");
thrd_exit(0);
}
}
}
int thread5(void* param)
{
puts("thread5 ok");
int thread1_result = 0;
int run_time = 0;
while(1)
{
run_time++;
sleep(1);
printf("thread5:run_time=%d\n",run_time);
if(run_time==3)
{
thrd_t curthr_id = thrd_current();
printf("thread5:curthr_id=%ld\n", curthr_id);
printf("Time: %s", ctime(&(time_t){time(NULL)}));
thrd_sleep(&(struct timespec){.tv_sec=5}, NULL);
printf("Time: %s", ctime(&(time_t){time(NULL)}));
}
if(run_time==6)
{
int err = thrd_create(&thread_6, thread6, NULL);
if(err!=thrd_success)
{
printf("\033[31merror:%s,in line %d:create thread6 failed:err=%d\033[0m\n", \
__FILE__, __LINE__, err);
}
}
if(run_time==8)
{
puts("thread5 exit.");
thrd_exit(0);
}
}
}
typedef struct
{
char name[32];
int run_time_max;
int sleep_time;
}thread7_param_t;
mtx_t mutex_sum;
bool mutex_sum_ok = false;
static int test_sum(const char* t_name, int runtime, int a, int b)
{
static int c = 0;
if(mutex_sum_ok)
{
mtx_lock(&mutex_sum);
}
c++;
int d = a + b + c;
printf("%s, test_sum(start%d): a=%d, b=%d, c=%d\n", t_name, runtime, a, b, c);
if(a>=100)
{
thrd_sleep(&(struct timespec){.tv_nsec=500000000}, NULL);
}
printf("%s, test_sum(end%d): a=%d, b=%d, c=%d\n", t_name, runtime, a, b, c);
int ret = a+b+c;
if(mutex_sum_ok)
{
mtx_unlock(&mutex_sum);
}
if(ret!=d)
{
printf("\033[31merror:%s,in line %d: %s, test_sum(%d) result error:ret=%d, d=%d\033[0m\n", \
__FILE__, __LINE__, t_name, runtime, ret, d);
}
return ret;
}
int thread7(void* param)
{
thread7_param_t* p_param = (thread7_param_t*)param;
printf("%s start\n", p_param->name);
printf("%s: sleep_time=%d ns\n", p_param->name, p_param->sleep_time);
int run_time = 0;
while(1)
{
run_time++;
thrd_sleep(&(struct timespec){.tv_nsec=p_param->sleep_time}, NULL);
printf("%s:run_time=%d\n", p_param->name, run_time);
int sum = test_sum(p_param->name, run_time, run_time*30, 1);
printf("%s: sum=%d\n", p_param->name, sum);
if(run_time==p_param->run_time_max)
{
printf("%s exit.\n", p_param->name);
thrd_exit(0);
}
}
}
void printf_all_thread_id(void)
{
printf("All thread id:\n");
printf("thread_1=%ld, thread_2=%ld\n", thread_1, thread_2);
printf("thread_3=%ld, thread_4=%ld\n", thread_3, thread_4);
printf("thread_5=%ld, thread_6=%ld\n", thread_5, thread_6);
printf("thread_7=%ld, thread_8=%ld\n", thread_7, thread_8);
printf("\n");
}
int test_t1_t2(void)
{
printf_all_thread_id();
printf("create thread1\n");
int err = thrd_create(&thread_1, thread1, NULL);
if(err!=thrd_success)
{
printf("\033[31merror:%s,in line %d:create thread1 failed:err=%d\033[0m\n", \
__FILE__, __LINE__, err);
}
printf("create thread2\n");
err = thrd_create(&thread_2, thread2, NULL);
if(err!=thrd_success)
{
printf("\033[31merror:%s,in line %d:create thread2 failed:err=%d\033[0m\n", \
__FILE__, __LINE__, err);
}
thrd_join(thread_2, NULL);
printf_all_thread_id();
}
int test_t3_t4(void)
{
printf_all_thread_id();
puts("create thread3");
int err = thrd_create(&thread_3, thread3, NULL);
if(err!=thrd_success)
{
printf("\033[31merror:%s,in line %d:create thread3 failed:err=%d\033[0m\n", \
__FILE__, __LINE__, err);
}
puts("create thread4");
err = thrd_create(&thread_4, thread4, NULL);
if(err!=thrd_success)
{
printf("\033[31merror:%s,in line %d:create thread4 failed:err=%d\033[0m\n", \
__FILE__, __LINE__, err);
}
thrd_join(thread_3, NULL);
thrd_join(thread_4, NULL);
printf_all_thread_id();
}
int test_t5_t6(void)
{
int err = thrd_create(&thread_5, thread5, NULL);
if(err!=thrd_success)
{
printf("\033[31merror:%s,in line %d:create thread5 failed:err=%d\033[0m\n", \
__FILE__, __LINE__, err);
}
printf("thread_5=%ld\n", thread_5);
thrd_join(thread_5, NULL);
thrd_join(thread_6, NULL);
printf_all_thread_id();
}
void test_t7_t8_mtx_init(void)
{
mtx_init(&mutex_sum, mtx_plain);
mutex_sum_ok = true;
}
void test_t7_t8_mtx_destroy(void)
{
mtx_destroy(&mutex_sum);
mutex_sum_ok = false;
}
int test_t7_t8(void)
{
thread7_param_t* param_thread7_1 = calloc(1, sizeof(thread7_param_t));
strcpy(param_thread7_1->name, "thread7_1");
param_thread7_1->run_time_max = 10;
param_thread7_1->sleep_time = 300000000;
int err = thrd_create(&thread_7, thread7, param_thread7_1);
if(err!=thrd_success)
{
printf("\033[31merror:%s,in line %d:create thread7 failed:err=%d\033[0m\n", \
__FILE__, __LINE__, err);
}
printf("thread_7=%ld\n", thread_7);
thread7_param_t* param_thread7_2 = calloc(1, sizeof(thread7_param_t));
strcpy(param_thread7_2->name, "thread7_2");
param_thread7_2->run_time_max = 10;
param_thread7_2->sleep_time = 600000000;
err = thrd_create(&thread_8, thread7, param_thread7_2);
if(err!=thrd_success)
{
printf("\033[31merror:%s,in line %d:create thread8 failed:err=%d\033[0m\n", \
__FILE__, __LINE__, err);
}
printf("thread_8=%ld\n", thread_8);
thrd_join(thread_7, NULL);
thrd_join(thread_8, NULL);
printf_all_thread_id();
}
int shared_data = 0;
mtx_t mtx_shared_data;
cnd_t cond_shared_data;
int thread_101(void* param)
{
printf("thread_101: start\n");
mtx_lock(&mtx_shared_data);
thrd_sleep(&(struct timespec){.tv_sec = 2}, NULL);
do
{
cnd_wait(&cond_shared_data, &mtx_shared_data);
printf("thread_101: woke up, shared_data = %d\n", shared_data);
} while (shared_data < 1000);
printf("thread_101: ok, shared_data = %d >= 1000\n", shared_data);
mtx_unlock(&mtx_shared_data);
printf("thread_101: exit\n");
thrd_exit(0);
}
int thread_102(void* param)
{
printf("thread_102: start\n");
mtx_lock(&mtx_shared_data);
thrd_sleep(&(struct timespec){.tv_sec = 2}, NULL);
do
{
cnd_wait(&cond_shared_data, &mtx_shared_data);
printf("thread_102: woke up, shared_data = %d\n", shared_data);
} while (shared_data < 800);
printf("thread_102: ok, shared_data = %d >= 800\n", shared_data);
mtx_unlock(&mtx_shared_data);
printf("thread_102: exit\n");
thrd_exit(0);
}
int thread_103(void* param)
{
printf("thread_103: start\n");
mtx_lock(&mtx_shared_data);
struct timespec ts;
timespec_get(&ts, TIME_UTC);
ts.tv_sec += 10;
int result = cnd_timedwait(&cond_shared_data, &mtx_shared_data, &ts);
if (result == thrd_success)
{
printf("thread_103: got it before timedout, shared_data = %d\n", shared_data);
}
else if (result == thrd_timedout)
{
printf("thread_103: timedout\n");
}
else
{
printf("thread_103: error\n");
}
mtx_unlock(&mtx_shared_data);
printf("thread_103: exit\n");
thrd_exit(0);
}
void make_signal(int data)
{
mtx_lock(&mtx_shared_data);
shared_data = data;
printf("make_signal: send signal to cond_shared_data\n");
cnd_signal(&cond_shared_data);
mtx_unlock(&mtx_shared_data);
}
int thread_104(void* param)
{
printf("thread_104: start\n");
thrd_sleep(&(struct timespec){.tv_sec = 5}, NULL);
for(int i = 1; i < 6; i++)
{
make_signal(i * 100);
thrd_sleep(&(struct timespec){.tv_sec = 1}, NULL);
}
printf("thread_104: exit\n");
thrd_exit(0);
}
void make_broadcast(int data)
{
mtx_lock(&mtx_shared_data);
shared_data = data;
printf("make_broadcast: send broadcast to cond_shared_data\n");
cnd_broadcast(&cond_shared_data);
mtx_unlock(&mtx_shared_data);
}
int thread_105(void* param)
{
printf("thread_105: start\n");
thrd_t t104 = *(thrd_t*)param;
thrd_join(t104, NULL);
printf("\n\nthread_105: thread_104 joined\n");
for(int i = 1; i < 12; i++)
{
make_broadcast(i * 100);
thrd_sleep(&(struct timespec){.tv_sec = 1}, NULL);
}
printf("thread_105: exit\n");
thrd_exit(0);
}
int test_cnd_mtx(void)
{
int err = mtx_init(&mtx_shared_data, mtx_plain);
if (err != thrd_success)
{
printf("\033[31merror:%s,in line %d:create mtx_shared_data failed:err=%d\033[0m\n", \
__FILE__, __LINE__, err);
return 1;
}
err = cnd_init(&cond_shared_data);
if (err != thrd_success)
{
printf("\033[31merror:%s,in line %d:create cond_shared_data failed:err=%d\033[0m\n", \
__FILE__, __LINE__, err);
mtx_destroy(&mtx_shared_data);
return 1;
}
thrd_t t101, t102, t103, t104, t105;
if (thrd_create(&t101, thread_101, NULL) != thrd_success)
{
printf("\033[31merror:%s,in line %d:create thread_101 failed\033[0m\n", \
__FILE__, __LINE__);
return 1;
}
if (thrd_create(&t102, thread_102, NULL) != thrd_success)
{
printf("\033[31merror:%s,in line %d:create thread_102 failed\033[0m\n", \
__FILE__, __LINE__);
return 1;
}
if (thrd_create(&t103, thread_103, NULL) != thrd_success)
{
printf("\033[31merror:%s,in line %d:create thread_103 failed\033[0m\n", \
__FILE__, __LINE__);
return 1;
}
if (thrd_create(&t104, thread_104, NULL) != thrd_success)
{
printf("\033[31merror:%s,in line %d:create thread_104 failed\033[0m\n", \
__FILE__, __LINE__);
return 1;
}
if (thrd_create(&t105, thread_105, &t104) != thrd_success)
{
printf("\033[31merror:%s,in line %d:create thread_105 failed\033[0m\n", \
__FILE__, __LINE__);
return 1;
}
thrd_join(t101, NULL);
thrd_join(t102, NULL);
thrd_join(t103, NULL);
thrd_join(t104, NULL);
thrd_join(t105, NULL);
cnd_destroy(&cond_shared_data);
mtx_destroy(&mtx_shared_data);
return 0;
}
thread_local int thread_local_data = 0;
tss_t tss_key_thread201;
tss_t tss_key_1;
tss_t tss_key_2;
tss_t tss_key_3;
typedef struct
{
char tss_name[64];
int tss_value;
int tss_data_len;
void* tss_data;
}thread201_tss_t;
typedef struct
{
char name[32];
thrd_t thread_id;
int set_thread_local_data;
}thread201_param_t;
void destroy_data(void* data)
{
thread201_tss_t* p_data = (thread201_tss_t*)data;
printf("destroy_data: %s, %d, %d, %s\n", \
p_data->tss_name, \
p_data->tss_value, \
p_data->tss_data_len, \
(char*)p_data->tss_data);
if(data!=NULL)
{
if(p_data->tss_data!=NULL)
{
free(p_data->tss_data);
}
free(data);
}
}
int generate_random_string(char **str)
{
if (str == NULL)
{
return -1;
}
int length = rand() % 65;
*str = (char *)malloc(length + 1);
if(*str == NULL)
{
return -1;
}
for (int i = 0; i < length; i++)
{
(*str)[i] = 33 + rand() % 94;
}
(*str)[length] = '\0';
return length + 1;
}
int thread_201(void* param)
{
thread201_param_t* p_param = (thread201_param_t*)param;
thread_local_data = p_param->set_thread_local_data;
thrd_sleep(&(struct timespec){.tv_sec = 1}, NULL);
printf("%s: thread_local_data = %d\n", p_param->name, thread_local_data);
thrd_sleep(&(struct timespec){.tv_sec = 1}, NULL);
thread201_tss_t* tss_data = (thread201_tss_t*)tss_get(tss_key_thread201);
if (tss_data == NULL)
{
tss_data = (thread201_tss_t*)calloc(1, sizeof(thread201_tss_t));
if(tss_data==NULL)
{
printf("\033[31merror:%s,in line %d:calloc tss_data failed\033[0m\n", \
__FILE__, __LINE__);
thrd_exit(1);
}
sprintf(tss_data->tss_name, "tss_data_%s", p_param->name);
tss_data->tss_value = p_param->set_thread_local_data * 10;
tss_data->tss_data_len = generate_random_string((char**)&tss_data->tss_data);
tss_set(tss_key_thread201, tss_data);
printf("%s: set tss_data: %s, %d, %d, %s\n", \
p_param->name, \
tss_data->tss_name, \
tss_data->tss_value, \
tss_data->tss_data_len, \
(char*)tss_data->tss_data);
}
else
{
printf("%s: set tss_data: %s, %d, %d, %s\n", \
p_param->name, \
tss_data->tss_name, \
tss_data->tss_value, \
tss_data->tss_data_len, \
(char*)tss_data->tss_data);
}
tss_data->tss_value += 1;
thrd_sleep(&(struct timespec){.tv_sec = 3}, NULL);
printf("%s: set tss_data: %s, %d, %d, %s\n", \
p_param->name, \
tss_data->tss_name, \
tss_data->tss_value, \
tss_data->tss_data_len, \
(char*)tss_data->tss_data);
printf("%s: exit\n", p_param->name);
thrd_exit(0);
}
int test_tss(void)
{
thread_local_data = 123;
if (tss_create(&tss_key_thread201, destroy_data) != thrd_success)
{
printf("\n");
printf("\033[31merror:%s,in line %d:create tss_key_thread201 failed\n\033[0m\n", \
__FILE__, __LINE__);
return 1;
}
printf("tss_key_thread201 = %d\n", tss_key_thread201);
if (tss_create(&tss_key_1, destroy_data) != thrd_success)
{
printf("\n");
printf("\033[31merror:%s,in line %d:create tss_key_1 failed\n\033[0m\n", \
__FILE__, __LINE__);
return 1;
}
printf("tss_key_1 = %d\n", tss_key_1);
thread201_param_t thread201_params[3];
memset(thread201_params, 0, sizeof(thread201_params));
for (int i = 0; i < 3; i++)
{
sprintf(thread201_params[i].name, "Thread201_%d", i + 1);
thread201_params[i].set_thread_local_data = (i + 1) * 10;
// sprintf(thread201_params[i].tss_data.tss_name, "tss_data_%d", i + 1);
// thread201_params[i].tss_data.tss_value = (i + 1) * 100;
// thread201_params[i].tss_data.tss_data = NULL;
if (thrd_create(&thread201_params[i].thread_id, thread_201, &thread201_params[i]) != thrd_success)
{
printf("\033[31merror:%s,in line %d:create thread_201_xx failed\n\033[0m\n", __FILE__, __LINE__);
return 1;
}
}
for (int i = 0; i < 3; i++) {
thrd_join(thread201_params[i].thread_id, NULL);
}
printf("main thread: thread_local_data = %d\n", thread_local_data);
tss_delete(tss_key_thread201);
printf("tss_key_1 = %d\n", tss_key_1);
if (tss_create(&tss_key_2, destroy_data) != thrd_success)
{
printf("\n");
printf("\033[31merror:%s,in line %d:create tss_key_2 failed\n\033[0m\n", __FILE__, __LINE__);
return 1;
}
printf("tss_key_2 = %d\n", tss_key_2);
if (tss_create(&tss_key_3, destroy_data) != thrd_success)
{
printf("\n");
printf("\033[31merror:%s,in line %d:create tss_key_3 failed\n\033[0m\n", __FILE__, __LINE__);
return 1;
}
printf("tss_key_3 = %d\n", tss_key_3);
tss_delete(tss_key_1);
tss_delete(tss_key_2);
tss_delete(tss_key_3);
return 0;
}
void test_thread(int (*func)(void), const char* name)
{
printf("\n===========================================================================\n");
printf("\033[32m%s\n\n\033[0m", name);
func();
printf("\033[32m\n\nend test %s\n\033[0m", name);
printf("===========================================================================\n");
}
int main(void)
{
int err = 0;
test_thread(test_t1_t2, "test_t1_t2");
test_thread(test_t3_t4, "test_t3_t4");
test_thread(test_t5_t6, "test_t5_t6");
test_thread(test_t7_t8, "test_t7_t8");
test_t7_t8_mtx_init();
test_thread(test_t7_t8, "test_t7_t8");
test_t7_t8_mtx_destroy();
test_thread(test_cnd_mtx, "test_cnd_mtx");
test_thread(test_tss, "test_tss");
return 0;
}