|
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