Skip to content

Commit 6e524f8

Browse files
committed
fix(tests): More generic multi-thread
This uses a combination of CMake and macros to detect and provide more generic code.
1 parent 7d07f74 commit 6e524f8

5 files changed

Lines changed: 105 additions & 24 deletions

File tree

test/CMakeLists.txt

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ file(GLOB_RECURSE "${OLD_PROJECT_NAME}_TESTS"
77
LIST_DIRECTORIES false
88
CONFIGURE_DEPENDS
99
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
10-
**/*.c
10+
vec/**/*.c
1111
)
1212

1313
list(JOIN "${OLD_PROJECT_NAME}_TESTS" " " testrunner_str)
@@ -20,6 +20,7 @@ create_test_sourcelist(
2020
# Additional libraries
2121
add_subdirectory("lib/")
2222

23+
# Test runner
2324
add_executable("${OLD_PROJECT_NAME}TestRunner" TestRunner.c ${${OLD_PROJECT_NAME}_TEST_SRC})
2425
add_executable("${OLD_PROJECT_NAME}::TestRunner" ALIAS "${OLD_PROJECT_NAME}TestRunner")
2526
add_executable("${PROJECT_NAME}::Runner" ALIAS "${OLD_PROJECT_NAME}TestRunner")
@@ -28,6 +29,46 @@ target_include_directories("${OLD_PROJECT_NAME}TestRunner" PRIVATE "include/")
2829
set_target_properties("${OLD_PROJECT_NAME}TestRunner" PROPERTIES
2930
CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/test")
3031

32+
# Check multithreading
33+
if(NOT DEFINED TRY_STDC_THREADS)
34+
message(CHECK_START "Test if <threads.h> is compiling")
35+
try_compile(TRY_STDC_THREADS
36+
SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/compiler/stdc_threads.c"
37+
)
38+
if(TRY_STDC_THREADS)
39+
message(CHECK_PASS "Success")
40+
else()
41+
message(CHECK_FAIL "Failure")
42+
endif()
43+
endif()
44+
45+
if(TRY_STDC_THREADS)
46+
set(THREAD_IMPL "C")
47+
set(THREAD_IMPL_ENUM 1)
48+
else(TRY_STDC_THREADS)
49+
#POSIX
50+
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
51+
find_package(Threads)
52+
if(CMAKE_USE_PTHREADS_INIT AND NOT DEFINED TRY_POSIX_THREADS)
53+
try_compile(TRY_POSIX_THREADS
54+
SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/compiler/stdc_threads.c"
55+
LINK_LIBRARIES Threads::Threads
56+
)
57+
endif(CMAKE_USE_PTHREADS_INIT AND NOT DEFINED TRY_POSIX_THREADS)
58+
if(TRY_POSIX_THREADS)
59+
set(THREAD_IMPL "POSIX")
60+
set(THREAD_IMPL_ENUM 2)
61+
target_link_libraries("${OLD_PROJECT_NAME}TestRunner" PRIVATE Threads::Threads)
62+
else(TRY_POSIX_THREADS)
63+
set(THREAD_IMPL "<none>")
64+
set(THREAD_IMPL_ENUM 0)
65+
endif(TRY_POSIX_THREADS)
66+
endif(TRY_STDC_THREADS)
67+
68+
message(STATUS "Threads implementation: ${THREAD_IMPL}")
69+
target_compile_definitions("${OLD_PROJECT_NAME}TestRunner"
70+
PRIVATE "DETECTED_THREAD_IMPL=${THREAD_IMPL_ENUM}")
71+
3172
foreach(test IN LISTS "${OLD_PROJECT_NAME}_TESTS")
3273
get_filename_component(TName "${test}" NAME_WE)
3374
get_filename_component(TPath "${test}" DIRECTORY)

test/compiler/posix_threads.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#include <pthread.h>
2+
#include <assert.h>
3+
4+
void* thr_fun(void* pass) {
5+
return pass;
6+
}
7+
8+
int main() {
9+
pthread_t thr;
10+
pthread_create(&thr, NULL, thr_fun, (void*) 0xADD);
11+
void* var=NULL;
12+
pthread_join(thr, &var);
13+
assert(var==0xADD);
14+
return 0;
15+
}

test/compiler/stdc_threads.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#include <threads.h>
2+
#include <assert.h>
3+
4+
int thr_fun(void*_) {
5+
return 0xADD;
6+
}
7+
8+
int main() {
9+
thrd_t thr;
10+
thrd_create(&thr, thr_fun, NULL);
11+
int var;
12+
thrd_join(thr, &var);
13+
assert(var==0xADD);
14+
return 0;
15+
}

test/vec/api/should_push_many.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ it_should(push_many) {
1717
test_if(vec.len == vec.reservd && vec.reservd == countof(A))
1818
goto exit;
1919
for(size_t i = 0; i < countof(A); ++i) {
20-
char tescase = -1;
2120
test_if(yavl_vec_get(&vec, i, &testcase) == YAVL_VEC_RES_OK)
2221
break;
2322
test_if(testcase == A[i]) {

test/vec/perf/should_push_not_slower_than_cpp.c

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,20 @@
66
#include <stdlib.h>
77
#include <time.h>
88
#include <stdio.h>
9-
#ifndef __STDC_NO_THREADS__
9+
10+
#if !defined(__STDC_NO_THREADS__) && DETECTED_THREAD_IMPL == 1 // C
1011
#include <threads.h>
12+
#define THREADS_INCLUDED 1
13+
#define THREAD_RET int
14+
#define THREAD_RET_OK thrd_success
15+
#elif DETECTED_THREAD_IMPL == 2 // POSIX
16+
#include <pthread.h>
17+
#define PTHREAD_INCLUDED 1
18+
#define THREAD_RET void*
19+
#define THREAD_RET_OK NULL
20+
#else
21+
#define THREAD_RET int
22+
#define THREAD_RET_OK 0
1123
#endif
1224

1325
static size_t default_reservd = 0;
@@ -18,7 +30,7 @@ typedef struct {
1830
size_t test_data_len;
1931
} bench_t;
2032

21-
static int bench_cpp(void* userdata) {
33+
static THREAD_RET bench_cpp(void* userdata) {
2234
bench_t *const data = userdata;
2335
struct timespec t[2] = {};
2436
cpp_vector(char) *cpp = NULL;
@@ -37,14 +49,10 @@ static int bench_cpp(void* userdata) {
3749
if(b)
3850
data->res_time += (((double)t[1].tv_nsec)/1e9)+(t[1].tv_sec);
3951
}
40-
#ifndef __STDC_NO_THREADS__
41-
return thrd_success;
42-
#else
43-
return 0;
44-
#endif
52+
return THREAD_RET_OK;
4553
}
4654

47-
static int bench_yavl(void* userdata) {
55+
static THREAD_RET bench_yavl(void* userdata) {
4856
bench_t *const data = userdata;
4957
struct timespec t[2] = {};
5058
yavl_vec_t yavl = YAVL_VEC_T_ALLOCATOR;
@@ -62,14 +70,10 @@ static int bench_yavl(void* userdata) {
6270
if(b)
6371
data->res_time += ((double)t[1].tv_nsec/1e9)+(t[1].tv_sec);
6472
}
65-
#ifndef __STDC_NO_THREADS__
66-
return thrd_success;
67-
#else
68-
return 0;
69-
#endif
73+
return THREAD_RET_OK;
7074
}
7175

72-
static int bench_inline(void* userdata) {
76+
static THREAD_RET bench_inline(void* userdata) {
7377
bench_t *const data = userdata;
7478
struct timespec t[2] = {};
7579
data->res_time=0;
@@ -98,11 +102,7 @@ static int bench_inline(void* userdata) {
98102
if(b)
99103
data->res_time += ((double)t[1].tv_nsec/1e9)+(t[1].tv_sec);
100104
}
101-
#ifndef __STDC_NO_THREADS__
102-
return thrd_success;
103-
#else
104-
return 0;
105-
#endif
105+
return THREAD_RET_OK;
106106
}
107107

108108
it_should(push_not_slower_than_cpp) {
@@ -129,9 +129,12 @@ it_should(push_not_slower_than_cpp) {
129129
{.test_data=tdata, .test_data_len=tdata_len},
130130
{.test_data=tdata, .test_data_len=tdata_len},
131131
};
132-
#ifndef __STDC_NO_THREADS__
132+
#if THREADS_INCLUDED
133133
thrd_t thr[3];
134134
thrd_start_t funs[3] = { bench_yavl,bench_cpp,bench_inline };
135+
#elif PTHREAD_INCLUDED
136+
pthread_t thr[3];
137+
typeof(&bench_yavl) funs[3] = { bench_yavl,bench_cpp,bench_inline };
135138
#else
136139
typeof(&bench_yavl) funs[3] = { bench_yavl,bench_cpp,bench_inline };
137140
#endif
@@ -145,19 +148,27 @@ it_should(push_not_slower_than_cpp) {
145148
ind[j] = temp;
146149
}
147150

148-
#ifndef __STDC_NO_THREADS__
151+
#if THREADS_INCLUDED || PTHREAD_INCLUDED
149152
printf("Running benchmarks in their own threads...\n");
150153
// Random thread creation, ordered thread collection
151154
for(size_t i=0;i<sizeof(thr)/sizeof(thr[0]);++i){
152155
printf(" * Starting \"%s\"...\n",strs[ind[i]]);
156+
#if THREADS_INCLUDED
153157
thrd_create(&thr[ind[i]], funs[ind[i]], &bdata[ind[i]]);
158+
#else
159+
pthread_create(&thr[ind[i]], NULL, funs[ind[i]], &bdata[ind[i]]);
160+
#endif
154161
}
155162
for(size_t i=0;i<sizeof(thr)/sizeof(thr[0]);++i){
163+
#if THREADS_INCLUDED
156164
thrd_join(thr[i], NULL);
165+
#else
166+
pthread_join(thr[i], NULL);
167+
#endif
157168
printf(" * \"%s\" finished! \n",strs[i]);
158169
}
159170
#else
160-
printf("Running in single thread only (no standard threads impl)\n");
171+
printf("Running in single thread only (no supported threads impl)\n");
161172
for(size_t i=0;i<sizeof(funs)/sizeof(funs[0]);++i){
162173
printf(" * Running \"%s\"...\n",strs[ind[i]]);
163174
funs[ind[i]](&bdata[ind[i]]);

0 commit comments

Comments
 (0)