|
7 | 7 | #include <chrono> |
8 | 8 | #include <condition_variable> |
9 | 9 | #include <functional> |
| 10 | +#include <iostream> |
10 | 11 | #include <mutex> |
11 | 12 | #include <thread> |
12 | 13 |
|
13 | 14 | class Thread : noncopyable |
14 | 15 | { |
15 | 16 | public: |
16 | | - using Task = std::function<void()>; |
| 17 | + using Task = std::function<void(std::stop_token)>; |
17 | 18 |
|
18 | 19 | Thread() = default; |
19 | | - explicit Thread(Task task) { setTask(std::move(task)); } |
| 20 | + |
| 21 | + explicit Thread(Task task) |
| 22 | + : m_task(std::move(task)) |
| 23 | + {} |
| 24 | + |
20 | 25 | ~Thread() { stop(); } |
21 | 26 |
|
22 | | - void setTask(Task task) { m_task = std::move(task); } |
| 27 | + void setTask(Task task) |
| 28 | + { |
| 29 | + std::lock_guard<std::mutex> lock(m_mutex); |
| 30 | + m_task = std::move(task); |
| 31 | + } |
23 | 32 |
|
24 | | - void start() |
| 33 | + bool start() |
25 | 34 | { |
| 35 | + if (m_jthread.joinable()) { |
| 36 | + return false; |
| 37 | + } |
| 38 | + |
26 | 39 | m_running.store(true); |
27 | | - m_thread = std::thread([this]() { |
28 | | - m_condition.notify_one(); |
29 | | - if (m_task) { |
30 | | - m_task(); |
| 40 | + m_jthread = std::jthread([this](std::stop_token token) { |
| 41 | + { |
| 42 | + std::unique_lock<std::mutex> lock(m_mutex); |
| 43 | + if (m_task) { |
| 44 | + try { |
| 45 | + m_task(token); |
| 46 | + } catch (const std::exception &e) { |
| 47 | + std::cerr << "Thread exception: " << e.what() << std::endl; |
| 48 | + } |
| 49 | + } |
31 | 50 | } |
| 51 | + |
| 52 | + m_running.store(false); |
| 53 | + m_running.notify_all(); |
32 | 54 | }); |
| 55 | + |
| 56 | + return true; |
33 | 57 | } |
34 | 58 |
|
35 | 59 | void stop() |
36 | 60 | { |
37 | | - if (m_thread.joinable()) { |
38 | | - m_thread.join(); |
| 61 | + if (m_jthread.joinable()) { |
| 62 | + m_jthread.request_stop(); |
| 63 | + m_jthread.join(); |
| 64 | + } |
| 65 | + } |
| 66 | + |
| 67 | + void interrupt() |
| 68 | + { |
| 69 | + if (m_jthread.joinable()) { |
| 70 | + m_jthread.request_stop(); |
39 | 71 | } |
40 | | - m_running.store(false); |
41 | 72 | } |
42 | 73 |
|
43 | | - void waitForStarted() |
| 74 | + void waitForFinished() |
44 | 75 | { |
45 | | - std::unique_lock<std::mutex> lock(m_mutex); |
46 | | - m_condition.wait(lock, [this]() { return m_running.load(); }); |
| 76 | + while (m_running.load()) { |
| 77 | + m_running.wait(true); |
| 78 | + } |
47 | 79 | } |
48 | 80 |
|
49 | | - [[nodiscard]] auto isRunning() const -> bool { return m_running; } |
| 81 | + [[nodiscard]] auto isRunning() const -> bool { return m_running.load(); } |
50 | 82 |
|
51 | | - [[nodiscard]] auto getThreadId() const -> std::thread::id { return m_thread.get_id(); } |
| 83 | + [[nodiscard]] auto getThreadId() const -> std::thread::id { return m_jthread.get_id(); } |
52 | 84 |
|
53 | 85 | static void yield() { std::this_thread::yield(); } |
54 | 86 |
|
| 87 | + static void sleep(unsigned int seconds) |
| 88 | + { |
| 89 | + std::this_thread::sleep_for(std::chrono::seconds(seconds)); |
| 90 | + } |
| 91 | + |
| 92 | + static void msleep(unsigned int milliseconds) |
| 93 | + { |
| 94 | + std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds)); |
| 95 | + } |
| 96 | + |
| 97 | + static void usleep(unsigned int microseconds) |
| 98 | + { |
| 99 | + std::this_thread::sleep_for(std::chrono::microseconds(microseconds)); |
| 100 | + } |
| 101 | + |
| 102 | + static void nsleep(unsigned int nanoseconds) |
| 103 | + { |
| 104 | + std::this_thread::sleep_for(std::chrono::nanoseconds(nanoseconds)); |
| 105 | + } |
| 106 | + |
55 | 107 | static void sleepFor(std::chrono::milliseconds duration) |
56 | 108 | { |
57 | 109 | std::this_thread::sleep_for(duration); |
58 | 110 | } |
59 | 111 |
|
60 | | - static void sleepUntil(std::chrono::system_clock::time_point timePoint) |
| 112 | + static void sleepUntil(const std::chrono::system_clock::time_point &wake_time) |
61 | 113 | { |
62 | | - std::this_thread::sleep_until(timePoint); |
| 114 | + std::this_thread::sleep_until(wake_time); |
63 | 115 | } |
64 | 116 |
|
65 | 117 | static auto hardwareConcurrency() -> unsigned int |
66 | 118 | { |
67 | | - auto availableCores = std::thread::hardware_concurrency(); // 如果不支持,返回0 |
| 119 | + auto availableCores = std::thread::hardware_concurrency(); |
68 | 120 | assert(availableCores > 0); |
69 | 121 | return availableCores; |
70 | 122 | } |
71 | 123 |
|
72 | 124 | private: |
73 | | - std::thread m_thread; |
| 125 | + std::jthread m_jthread; |
74 | 126 | std::atomic_bool m_running{false}; |
75 | 127 | std::mutex m_mutex; |
76 | | - std::condition_variable m_condition; |
77 | 128 | Task m_task; |
78 | 129 | }; |
0 commit comments