1 | // |
---|---|
2 | // Thread_STD.cpp |
3 | // |
4 | // Library: Foundation |
5 | // Package: Threading |
6 | // Module: Thread |
7 | // |
8 | // Copyright (c) 2004-2007, Applied Informatics Software Engineering GmbH. |
9 | // and Contributors. |
10 | // |
11 | // SPDX-License-Identifier: BSL-1.0 |
12 | // |
13 | |
14 | |
15 | #include "Poco/Thread_STD.h" |
16 | #include "Poco/Thread.h" |
17 | #include "Poco/Exception.h" |
18 | #include "Poco/ErrorHandler.h" |
19 | #include "Poco/Format.h" |
20 | #if defined(POCO_OS_FAMILY_WINDOWS) |
21 | #include "Thread_STD_WIN32.cpp" |
22 | #elif defined(POCO_VXWORKS) |
23 | #include "Thread_STD_VX.cpp" |
24 | #else |
25 | #include "Thread_STD_POSIX.cpp" |
26 | #endif |
27 | |
28 | |
29 | namespace Poco { |
30 | |
31 | |
32 | ThreadImpl::CurrentThreadHolder ThreadImpl::_currentThreadHolder; |
33 | thread_local ThreadImpl* ThreadImpl::CurrentThreadHolder::_pThread; |
34 | |
35 | |
36 | ThreadImpl::ThreadImpl(): _pData(new ThreadData) |
37 | { |
38 | } |
39 | |
40 | |
41 | ThreadImpl::~ThreadImpl() |
42 | { |
43 | if (_pData->started && !_pData->joined && _pData->thread) |
44 | { |
45 | _pData->thread->detach(); |
46 | } |
47 | } |
48 | |
49 | |
50 | void ThreadImpl::startImpl(SharedPtr<Runnable> pTarget) |
51 | { |
52 | if (_pData->pRunnableTarget) |
53 | throw SystemException("thread already running"); |
54 | |
55 | _pData->pRunnableTarget = pTarget; |
56 | try |
57 | { |
58 | _pData->thread = std::unique_ptr<std::thread>(new std::thread(runnableEntry, this)); |
59 | } |
60 | catch (std::system_error &e) { |
61 | _pData->pRunnableTarget = 0; |
62 | throw SystemException(Poco::format("cannot start thread: %s", std::string(e.what()))); |
63 | } |
64 | |
65 | _pData->tid = _pData->thread->native_handle(); |
66 | |
67 | _pData->started = true; |
68 | } |
69 | |
70 | |
71 | void ThreadImpl::joinImpl() |
72 | { |
73 | if (!_pData->started) return; |
74 | _pData->done.wait(); |
75 | try |
76 | { |
77 | _pData->thread->join(); |
78 | } |
79 | catch (std::system_error &e) { |
80 | throw SystemException(Poco::format("cannot join thread: %s", std::string(e.what()))); |
81 | } |
82 | |
83 | _pData->joined = true; |
84 | } |
85 | |
86 | |
87 | bool ThreadImpl::joinImpl(long milliseconds) |
88 | { |
89 | if (_pData->started && _pData->done.tryWait(milliseconds)) |
90 | { |
91 | try |
92 | { |
93 | _pData->thread->join(); |
94 | } |
95 | catch (std::system_error &e) { |
96 | throw SystemException(Poco::format("cannot join thread: %s", std::string(e.what()))); |
97 | } |
98 | _pData->joined = true; |
99 | return true; |
100 | } |
101 | else if (_pData->started) return false; |
102 | else return true; |
103 | } |
104 | |
105 | |
106 | ThreadImpl* ThreadImpl::currentImpl() |
107 | { |
108 | return _currentThreadHolder.get(); |
109 | } |
110 | |
111 | |
112 | ThreadImpl::TIDImpl ThreadImpl::currentTidImpl() |
113 | { |
114 | ThreadImpl* pThreadImpl = currentImpl(); |
115 | if (!pThreadImpl) |
116 | return 0; |
117 | |
118 | return pThreadImpl->tidImpl(); |
119 | //return std::this_thread::get_id(); |
120 | } |
121 | |
122 | |
123 | void ThreadImpl::sleepImpl(long milliseconds) |
124 | { |
125 | std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds)); |
126 | } |
127 | |
128 | |
129 | void* ThreadImpl::runnableEntry(void* pThread) |
130 | { |
131 | _currentThreadHolder.set(reinterpret_cast<ThreadImpl*>(pThread)); |
132 | |
133 | ThreadImpl* pThreadImpl = reinterpret_cast<ThreadImpl*>(pThread); |
134 | |
135 | AutoPtr<ThreadData> pData = pThreadImpl->_pData; |
136 | |
137 | try |
138 | { |
139 | pData->pRunnableTarget->run(); |
140 | } |
141 | catch (Exception& exc) |
142 | { |
143 | ErrorHandler::handle(exc); |
144 | } |
145 | catch (std::exception& exc) |
146 | { |
147 | ErrorHandler::handle(exc); |
148 | } |
149 | catch (...) |
150 | { |
151 | ErrorHandler::handle(); |
152 | } |
153 | |
154 | pData->pRunnableTarget = 0; |
155 | pData->done.set(); |
156 | return 0; |
157 | } |
158 | |
159 | |
160 | } // namespace Poco |
161 |