• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

devmarkusb / util / 23399309665

22 Mar 2026 08:36AM UTC coverage: 88.255% (-0.002%) from 88.257%
23399309665

push

github

MarkusB
Refactor `new_statistics` to remove `UL_I_AM_SURE_TO_REPLACE_NEW_DELETE` macro and improve `str_convert` structure implementation.

15 of 15 new or added lines in 2 files covered. (100.0%)

5 existing lines in 3 files now uncovered.

5816 of 6590 relevant lines covered (88.25%)

347.08 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

6.48
/basiccodesupport/src/thread/pin.test.cpp
1
#include "ul/thread/pin.h"
2
#include "ul/macros.h"
3
#include "gtest/gtest.h"
4
#include <algorithm>
5
#include <chrono>
6
#include <condition_variable>
7
#include <mutex>
8
#include <stdexcept>
9
#include <thread>
10
#include <vector>
11

12
#if UL_OS_LINUX
13
namespace ul = mb::ul;
14

15
constexpr auto num_waits{5};
16
#endif
17

18
class PinToCpuTest : public testing::Test {
19
protected:
20
    struct Ready2go {
21
        std::mutex m;
22
        std::condition_variable cv;
23
        bool ok{false};
24
    };
25
};
26

27
#if !UL_OS_LINUX // mac also not working yet
28
TEST_F(PinToCpuTest, DISABLED_twoThreadsPinnedToFirstTwoCPUs_okFor10msCheckedEach2ms) {
29
}
30
#else
31
TEST_F(PinToCpuTest, DISABLED_twoThreadsPinnedToFirstTwoCPUs_okFor10msCheckedEach2ms) {
×
32
    const auto num_threads = std::min(2u, std::thread::hardware_concurrency());
×
33
    ASSERT_GE(num_threads, 2u); // get some modern system for development!
×
34

35
    std::vector<std::thread> threads;
×
36
    std::vector<Ready2go> ready2go(num_threads);
×
37
    for (auto i = decltype(num_threads){0}; i < num_threads; ++i) {
×
38
        threads.emplace_back([i, &ready2go] {
×
39
            std::unique_lock<std::mutex> lk(ready2go[i].m);
40
            ready2go[i].cv.wait(lk, [i, &ready2go] {
41
                return ready2go[i].ok;
42
            });
43
            lk.unlock();
44
            for (auto j = 0; j < num_waits; ++j) {
45
                EXPECT_EQ(static_cast<int>(i), ul::thread::num_logical_cores());
46
                std::this_thread::sleep_for(std::chrono::milliseconds(2));
47
            }
48
        });
49
        ul::thread::pin_to_logical_core(threads[i], static_cast<int>(i));
×
50
        {
51
            const std::lock_guard<std::mutex> lk(ready2go[i].m);
×
52
            ready2go[i].ok = true;
×
53
        }
×
54
        ready2go[i].cv.notify_one();
×
55
    }
56
    for (auto& t : threads) {
×
57
        t.join();
×
58
    }
×
59
}
×
60
#endif
×
61

×
62
#if !UL_OS_LINUX // mac also not working yet
×
63
TEST_F(PinToCpuTest, DISABLED_twoThreadsPinnedToSecondCPUOnly_okFor10msCheckedEach2ms) {
×
64
}
×
65
#else
×
66
TEST_F(PinToCpuTest, DISABLED_twoThreadsPinnedToSecondCPUOnly_okFor10msCheckedEach2ms) {
×
67
    const auto num_threads = std::min(2u, std::thread::hardware_concurrency());
×
68
    ASSERT_GE(num_threads, 2u); // get some modern system for development!
×
69

70
    std::vector<std::thread> threads(num_threads);
×
71
    std::vector<Ready2go> ready2go(num_threads);
×
72
    for (auto i = decltype(num_threads){0}; i < num_threads; ++i) {
×
73
        threads[i] = std::thread([i, &ready2go] {
×
74
            std::unique_lock<std::mutex> lk(ready2go[i].m);
75
            ready2go[i].cv.wait(lk, [i, &ready2go] {
76
                return ready2go[i].ok;
77
            });
78
            lk.unlock();
79
            for (auto j = 0; j < num_waits; ++j) {
80
                EXPECT_EQ(1, ul::thread::num_logical_cores());
81
                std::this_thread::sleep_for(std::chrono::milliseconds(2));
82
            }
83
        });
×
84
        ul::thread::pin_to_logical_core(threads[i], 1);
×
85
        {
86
            const std::lock_guard<std::mutex> lk(ready2go[i].m);
×
87
            ready2go[i].ok = true;
×
88
        }
×
89
        ready2go[i].cv.notify_one();
×
90
    }
91
    for (auto& t : threads) {
×
92
        t.join();
×
93
    }
×
94
}
×
95
#endif
×
96

×
97
#if !UL_OS_LINUX // mac also not working yet
×
98
TEST_F(PinToCpuTest, DISABLED_twoThreadsPinnedToFirstTwoCPUsSwitchedAfter3rdCheck_okFor50msCheckedEach5ms) {
×
99
}
×
100
#else
101
// NOLINTBEGIN
102
TEST_F(PinToCpuTest, DISABLED_twoThreadsPinnedToFirstTwoCPUsSwitchedAfter3rdCheck_okFor50msCheckedEach5ms) {
×
103
    const auto num_threads = std::min(2u, std::thread::hardware_concurrency());
×
104
    ASSERT_GE(num_threads, 2u); // get some modern system for development!
×
105

106
    std::vector<std::thread> threads(num_threads);
×
107
    std::vector<Ready2go> ready2go(num_threads);
×
108
    bool switched{};
×
109
    std::mutex switched_m;
×
110
    auto switchCores = [&threads, &num_threads]() {
111
        for (auto i = decltype(num_threads){0}; i < num_threads; ++i) {
112
            ul::thread::pin_to_logical_core(threads[i], static_cast<int>(i + 1 % num_threads));
113
        }
114
    };
×
115
    for (auto i = decltype(num_threads){0}; i < num_threads; ++i) {
×
116
        threads[i] = std::thread([i, &ready2go, &switched, &switched_m, &switchCores, &num_threads] {
×
117
            std::unique_lock<std::mutex> lk(ready2go[i].m);
118
            ready2go[i].cv.wait(lk, [i, &ready2go] {
119
                return ready2go[i].ok;
120
            });
121
            lk.unlock();
122
            for (auto j = 0; j < num_waits * 2; ++j) {
123
                {
124
                    const std::lock_guard<std::mutex> switch_lk(switched_m);
125
                    if (!switched) {
126
                        EXPECT_EQ(static_cast<int>(i), ul::thread::num_logical_cores());
127
                        if (j == 2) {
128
                            switched = true;
129
                            switchCores();
130
                        }
131
                    } else {
132
                        EXPECT_EQ(static_cast<int>(i + 1u % num_threads), ul::thread::num_logical_cores());
133
                    }
134
                }
135
                std::this_thread::sleep_for(std::chrono::milliseconds(num_waits));
136
            }
137
        });
×
138
        ul::thread::pin_to_logical_core(threads[i], static_cast<int>(i));
×
139
        {
140
            const std::lock_guard<std::mutex> lk(ready2go[i].m);
×
141
            ready2go[i].ok = true;
×
142
        }
×
143
        ready2go[i].cv.notify_one();
×
144
    }
145
    for (auto& t : threads) {
×
146
        t.join();
×
147
    }
×
148
}
×
149

×
150
// NOLINTEND
×
151
#endif
×
152

×
153
#if !UL_OS_LINUX // mac also not working yet
×
154
TEST_F(PinToCpuTest, DISABLED_maxThreadsPinnedToSeparateCPUs_okFor10msCheckedEach2ms) {
×
155
}
×
156
#else
×
157
TEST_F(PinToCpuTest, DISABLED_maxThreadsPinnedToSeparateCPUs_okFor10msCheckedEach2ms) {
×
158
    const auto num_threads = std::thread::hardware_concurrency();
×
159
    ASSERT_GT(num_threads, 0u); // hardware_concurrency failed
×
160

×
161
    std::vector<std::thread> threads(num_threads);
×
162
    std::vector<Ready2go> ready2go(num_threads);
×
163
    for (auto i = decltype(num_threads){0}; i < num_threads; ++i) {
×
164
        threads[i] = std::thread([i, &ready2go] {
×
165
            std::unique_lock<std::mutex> lk(ready2go[i].m);
×
166
            ready2go[i].cv.wait(lk, [i, &ready2go] {
×
167
                return ready2go[i].ok;
×
168
            });
×
169
            lk.unlock();
×
UNCOV
170
            for (auto j = 0; j < num_waits; ++j) {
×
171
                EXPECT_EQ(static_cast<int>(i), ul::thread::num_logical_cores());
172
                std::this_thread::sleep_for(std::chrono::milliseconds(2));
173
            }
174
        });
×
175
        ul::thread::pin_to_logical_core(threads[i], static_cast<int>(i));
×
176
        {
177
            const std::lock_guard<std::mutex> lk(ready2go[i].m);
×
178
            ready2go[i].ok = true;
×
179
        }
×
180
        ready2go[i].cv.notify_one();
×
181
    }
182
    for (auto& t : threads) {
×
183
        t.join();
×
184
    }
×
185
}
×
186
#endif
×
187

×
188
#if !UL_OS_LINUX // mac also not working yet
×
189
TEST_F(PinToCpuTest, DISABLED_invalidCPUNr_throws) {
×
190
}
×
191
#else
192
TEST_F(PinToCpuTest, invalidCPUNr_throws) {
4✔
193
    std::thread thread([] {
1✔
194
    });
2✔
195
    EXPECT_THROW(
1✔
196
        ul::thread::pin_to_logical_core(thread, 1 + static_cast<int>(std::thread::hardware_concurrency())),
197
        std::runtime_error);
1✔
198
    thread.join();
1✔
199
}
1✔
200
#endif
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc