1 /*
2  * Copyright 2022 Yonggang Luo
3  * SPDX-License-Identifier: MIT
4  *
5  * Testing u_call_once.h
6  */
7 
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <gtest/gtest.h>
11 
12 #include "c11/threads.h"
13 #include "util/u_atomic.h"
14 #include "util/u_call_once.h"
15 
16 #define NUM_DEBUG_TEST_THREAD 8
17 
update_x(int * x)18 static void update_x(int *x) {
19    p_atomic_inc(x);
20 }
21 
22 static int xC;
update_x_global(void)23 static void update_x_global(void)
24 {
25    update_x(&xC);
26 }
27 
test_call_once(void * _state)28 static int test_call_once(void *_state)
29 {
30    static int xA = 0;
31    {
32       static once_flag once = ONCE_FLAG_INIT;
33       for (int i = 0; i < 100; i += 1) {
34          util_call_once_data_slow(&once, (util_call_once_data_func)update_x, &xA);
35       }
36    }
37 
38    static int xB = 0;
39    {
40       static util_once_flag once = UTIL_ONCE_FLAG_INIT;
41       for (int i = 0; i < 100; i += 1) {
42          util_call_once_data(&once, (util_call_once_data_func)update_x, &xB);
43       }
44    }
45    {
46       static util_once_flag once = UTIL_ONCE_FLAG_INIT;
47       for (int i = 0; i < 100; i += 1) {
48          util_call_once(&once, update_x_global);
49       }
50    }
51    EXPECT_EQ(xA, 1);
52    EXPECT_EQ(xB, 1);
53    EXPECT_EQ(xC, 1);
54    return 0;
55 }
56 
TEST(UtilCallOnce,Multithread)57 TEST(UtilCallOnce, Multithread)
58 {
59    thrd_t threads[NUM_DEBUG_TEST_THREAD];
60    for (unsigned i = 0; i < NUM_DEBUG_TEST_THREAD; i++) {
61         thrd_create(&threads[i], test_call_once, NULL);
62    }
63    for (unsigned i = 0; i < NUM_DEBUG_TEST_THREAD; i++) {
64       int ret;
65       thrd_join(threads[i], &ret);
66    }
67 }
68