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
29namespace Poco {
30
31
32ThreadImpl::CurrentThreadHolder ThreadImpl::_currentThreadHolder;
33thread_local ThreadImpl* ThreadImpl::CurrentThreadHolder::_pThread;
34
35
36ThreadImpl::ThreadImpl(): _pData(new ThreadData)
37{
38}
39
40
41ThreadImpl::~ThreadImpl()
42{
43 if (_pData->started && !_pData->joined && _pData->thread)
44 {
45 _pData->thread->detach();
46 }
47}
48
49
50void 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
71void 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
87bool 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
106ThreadImpl* ThreadImpl::currentImpl()
107{
108 return _currentThreadHolder.get();
109}
110
111
112ThreadImpl::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
123void ThreadImpl::sleepImpl(long milliseconds)
124{
125 std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds));
126}
127
128
129void* 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