DotNetDupe 4.0.6
C++17/20 Implementation of the .NET Base Class Library (BCL)
Loading...
Searching...
No Matches
Thread.cpp
Go to the documentation of this file.
1#include "pch.h"
6#include <chrono>
7#include <memory>
8#include <thread>
9#include <atomic>
10#include <mutex>
11#include <condition_variable>
12
13#if defined(_WIN32)
14#include <windows.h>
15#else
16#include <unistd.h>
17#include <sys/syscall.h>
18#endif
19
20namespace DotNetDupe {
21 namespace System {
22 namespace Threading {
23
24 struct Thread::Impl {
25 std::unique_ptr<std::thread> internalThread;
26 ThreadStart start;
27 ParameterizedThreadStart parameterizedStart;
28 String name;
29 std::atomic<bool> isAlive{false};
30 bool completed{false};
31 std::mutex joinMutex;
32 std::condition_variable joinCv;
33 };
34
35 thread_local Thread* Thread::_currentThread = nullptr;
36 static thread_local SmartPointer<Thread> s_pCurrentThreadStorage(nullptr);
37
39 : m_pImpl(new Impl()) {
40 m_pImpl->start = start;
41 }
42
44 : m_pImpl(new Impl()) {
45 m_pImpl->parameterizedStart = start;
46 }
47
49 : m_pImpl(new Impl()) {
50 m_pImpl->isAlive = true;
51 }
52
53 static void SafelyJoinOrDetach(const std::unique_ptr<std::thread>& pThread) {
55 if (!pThread || !pThread->joinable()) return;
56
58 try {
59 if (pThread->get_id() == std::this_thread::get_id()) {
60 pThread->detach();
61 } else {
62 pThread->join();
63 }
64 } catch (...) {
65 (void)0; // Suppress exceptions during thread teardown to ensure noexcept safety
66 }
67 }
68
71 if (m_pImpl) {
72 SafelyJoinOrDetach(m_pImpl->internalThread);
73 delete m_pImpl;
74 m_pImpl = nullptr;
75 }
76 }
77
79 Start(nullptr);
80 }
81
82 void Thread::Start(Object* parameter) {
84 if (!m_pImpl || m_pImpl->isAlive) return;
85
87 m_pImpl->isAlive = true;
88 m_pImpl->completed = false;
89 m_pImpl->internalThread = std::make_unique<std::thread>(&Thread::ThreadMain, this, parameter);
90 }
91
92 void Thread::Join() {
94 if (!m_pImpl || !m_pImpl->internalThread || !m_pImpl->internalThread->joinable()) return;
95 if (m_pImpl->internalThread->get_id() == std::this_thread::get_id()) return;
96
98 m_pImpl->internalThread->join();
99 }
100
101 bool Thread::Join(int millisecondsTimeout) {
103 if (!m_pImpl) return true;
104 if (!m_pImpl->isAlive && m_pImpl->completed) return true;
105 if (!m_pImpl->internalThread) return true;
106
108 std::unique_lock<std::mutex> lock(m_pImpl->joinMutex);
109 if (m_pImpl->joinCv.wait_for(lock, std::chrono::milliseconds(millisecondsTimeout), [this]() { return m_pImpl->completed; })) {
110 if (m_pImpl->internalThread->joinable()) {
111 m_pImpl->internalThread->join();
112 }
113 return true;
114 }
115
117 throw TimeoutException("The thread did not terminate within the allotted time.");
118 }
119
120 void Thread::Sleep(int millisecondsTimeout) {
122 std::this_thread::sleep_for(std::chrono::milliseconds(millisecondsTimeout));
123 }
124
125 bool Thread::IsAlive() const {
126 return m_pImpl ? m_pImpl->isAlive.load() : false;
127 }
128
130 return m_pImpl ? m_pImpl->name : String("");
131 }
132
133 void Thread::SetName(const String& name) {
134 if (m_pImpl) m_pImpl->name = name;
135 }
136
139 if (_currentThread == nullptr) {
140 s_pCurrentThreadStorage = CreateCurrentThreadWrapper();
141 _currentThread = s_pCurrentThreadStorage.Get();
142 }
143
145 return _currentThread;
146 }
147
150#if defined(_WIN32)
151 return static_cast<int>(::GetCurrentThreadId());
152#else
153 return static_cast<int>(::syscall(__NR_gettid));
154#endif
155 }
156
157 SmartPointer<Thread> Thread::CreateCurrentThreadWrapper() {
158 return SmartPointer<Thread>(new Thread(), true);
159 }
160
161 void Thread::ThreadMain(Object* parameter) {
163 _currentThread = this;
164
166 try {
167 if (m_pImpl->start) m_pImpl->start();
168 else if (m_pImpl->parameterizedStart) m_pImpl->parameterizedStart(parameter);
169 } catch (...) {
170 (void)0;
171 }
172
174 {
175 std::lock_guard<std::mutex> lock(m_pImpl->joinMutex);
176 m_pImpl->completed = true;
177 m_pImpl->isAlive = false;
178 }
179
181 m_pImpl->joinCv.notify_all();
182 }
183 }
184 }
185}
Provides reference-counted and weak pointer memory management primitives ensuring zero raw ownership.
Creates and controls a thread, sets its priority, and gets its status mirroring .NET System....
Defines the exception thrown when the time allotted for a process or operation has expired.
Represents an unknown or unmapped exception encountered during execution.
Supports all classes in the DotNetDupe class hierarchy.
Definition Object.h:18
A unified smart pointer that supports both unique and shared ownership semantics.
Represents text as a sequence of UTF-8 code units with culture-invariant operations.
Definition String.h:74
String()
Initializes a new instance of the String class to an empty string.
Definition String.cpp:64
Creates and controls execution of operating system threads.
Definition Thread.h:28
String GetName() const
Gets the friendly name of the thread.
Definition Thread.cpp:129
static int GetCurrentThreadId()
Returns an integer identifier for the current managed thread.
Definition Thread.cpp:148
Thread(ThreadStart start)
Initializes a new instance of the Thread class with a parameterless start delegate.
Definition Thread.cpp:38
void Join()
Blocks the calling thread until the thread represented by this instance terminates.
Definition Thread.cpp:92
void Start()
Causes the operating system to change the state of the current instance to Running.
Definition Thread.cpp:78
static void Sleep(int millisecondsTimeout)
Suspends the current thread for the specified number of milliseconds.
Definition Thread.cpp:120
bool IsAlive() const
Gets a value indicating the execution status of the current thread.
Definition Thread.cpp:125
static Thread * GetCurrentThread()
Gets the currently running thread.
Definition Thread.cpp:137
void SetName(const String &name)
Sets the friendly name of the thread.
Definition Thread.cpp:133
TimeoutException(const String &sMessage)
Initializes a new instance of the TimeoutException class with a specified error message.
static void SafelyJoinOrDetach(const std::unique_ptr< std::thread > &pThread)
Definition Thread.cpp:53
Action< Object * > ParameterizedThreadStart
Definition Thread.h:17
static SmartPointer< Thread > s_pCurrentThreadStorage(nullptr)